|
82986
|
2868
|
33
|
2026-05-28T09:59:33.580694+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779962373580_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Code changed:
Hide
Sync Changes
Hide This Notification
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01';
and id IN (32415, 32416);
# and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
SELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436
SELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses
FROM text_relays
WHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')
GROUP BY email_provider_id;
SELECT id, status, telephony_provider_id, created_at
FROM activities
WHERE id IN (80028719, 80028846);
SELECT id, status, code, email_sent_at, created_at, updated_at
FROM text_relays
WHERE id IN (32415, 32416);
SELECT id, status, code, sender, recipient, created_at
FROM text_relays
WHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'
ORDER BY created_at DESC
LIMIT 10;
SELECT id, uuid, status, code, sender, recipient, created_at, updated_at
FROM text_relays
WHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');
# [PASSWORD_DOTS]
SELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count
FROM users u
INNER JOIN activities a ON u.id = .user_id
WHERE a.type LIKE 'sms%'
AND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY u.id, u.email, u.name, u.softphone_number
ORDER BY sms_count DESC;
select * from teams where id = 1;
select * from roles;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1117 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES
SELECT * FROM activities WHERE uuid_to_bin('[CREDIT_CARD]-927f-4f4da2a8185c') = uuid; # 80186192 NO
SELECT * FROM crm_configurations WHERE id = 1053;
SELECT * FROM teams WHERE id = 1117;
select * from users where id = 30249;
select * from playbooks where id = 5473;
select * from playbook_categories where id = 43783;
select * from playbook_categories where playbook_id = 5473;
select * from crm_fields where id = 659242;
select * from crm_field_values where crm_field_id = 659242;
SELECT * FROM crm_field_data fd
# JOIN crm_fields f ON fd.crm_field_id = f.id
# JOIN activities a ON fd.activity_id = a.id
WHERE activity_id = 79933459
# AND f.crm_provider_id = 'hs_activity_type';
SELECT * FROM activity_messages;
select * from text_relays where created_at > '2026-05-01';
select * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;
select * from users where team_id = 1 and id IN (18608, 13934, 7160);
select * from activities where user_id = 7160 order by id desc limit 10;
select * from accounts where team_id = 1 and name = 'Column5';
select * from users where name like '%Subra%'; # 31054, 1117
select * from teams where id = 1117;
select * from activity_searches where user_id = 31054;
select * from activity_search_filters where activity_search_id IN (88882, 88902);
Project
Project
New File or Directory…
Expand Selected
Collapse All...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.5006649,"top":0.07581804,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.5099734,"top":0.07581804,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.5212766,"top":0.074221864,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.52859044,"top":0.074221864,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.53723407,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.54587764,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.5568484,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.56549203,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.57413566,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.5851064,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.59607714,"top":0.074221864,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.62267286,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.6336436,"top":0.074221864,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9587766,"top":0.074221864,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"45","depth":4,"bounds":{"left":0.9288564,"top":0.09896249,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.9411569,"top":0.09896249,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"41","depth":4,"bounds":{"left":0.95046544,"top":0.09896249,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"66","depth":4,"bounds":{"left":0.96210104,"top":0.09896249,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9740692,"top":0.09736632,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.98138297,"top":0.09736632,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4032223961605137191
|
2218652917440067151
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Code changed:
Hide
Sync Changes
Hide This Notification
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01';
and id IN (32415, 32416);
# and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
SELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436
SELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses
FROM text_relays
WHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')
GROUP BY email_provider_id;
SELECT id, status, telephony_provider_id, created_at
FROM activities
WHERE id IN (80028719, 80028846);
SELECT id, status, code, email_sent_at, created_at, updated_at
FROM text_relays
WHERE id IN (32415, 32416);
SELECT id, status, code, sender, recipient, created_at
FROM text_relays
WHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'
ORDER BY created_at DESC
LIMIT 10;
SELECT id, uuid, status, code, sender, recipient, created_at, updated_at
FROM text_relays
WHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');
# [PASSWORD_DOTS]
SELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count
FROM users u
INNER JOIN activities a ON u.id = .user_id
WHERE a.type LIKE 'sms%'
AND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY u.id, u.email, u.name, u.softphone_number
ORDER BY sms_count DESC;
select * from teams where id = 1;
select * from roles;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1117 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES
SELECT * FROM activities WHERE uuid_to_bin('[CREDIT_CARD]-927f-4f4da2a8185c') = uuid; # 80186192 NO
SELECT * FROM crm_configurations WHERE id = 1053;
SELECT * FROM teams WHERE id = 1117;
select * from users where id = 30249;
select * from playbooks where id = 5473;
select * from playbook_categories where id = 43783;
select * from playbook_categories where playbook_id = 5473;
select * from crm_fields where id = 659242;
select * from crm_field_values where crm_field_id = 659242;
SELECT * FROM crm_field_data fd
# JOIN crm_fields f ON fd.crm_field_id = f.id
# JOIN activities a ON fd.activity_id = a.id
WHERE activity_id = 79933459
# AND f.crm_provider_id = 'hs_activity_type';
SELECT * FROM activity_messages;
select * from text_relays where created_at > '2026-05-01';
select * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;
select * from users where team_id = 1 and id IN (18608, 13934, 7160);
select * from activities where user_id = 7160 order by id desc limit 10;
select * from accounts where team_id = 1 and name = 'Column5';
select * from users where name like '%Subra%'; # 31054, 1117
select * from teams where id = 1117;
select * from activity_searches where user_id = 31054;
select * from activity_search_filters where activity_search_id IN (88882, 88902);
Project
Project
New File or Directory…
Expand Selected
Collapse All...
|
82985
|
NULL
|
NULL
|
NULL
|
|
82984
|
2868
|
31
|
2026-05-28T09:59:28.316846+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779962368316_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Code changed:
Hide
Sync Changes
Hide This Notification
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01';
and id IN (32415, 32416);
# and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
SELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436
SELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses
FROM text_relays
WHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')
GROUP BY email_provider_id;
SELECT id, status, telephony_provider_id, created_at
FROM activities
WHERE id IN (80028719, 80028846);
SELECT id, status, code, email_sent_at, created_at, updated_at
FROM text_relays
WHERE id IN (32415, 32416);
SELECT id, status, code, sender, recipient, created_at
FROM text_relays
WHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'
ORDER BY created_at DESC
LIMIT 10;
SELECT id, uuid, status, code, sender, recipient, created_at, updated_at
FROM text_relays
WHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');
# [PASSWORD_DOTS]
SELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count
FROM users u
INNER JOIN activities a ON u.id = .user_id
WHERE a.type LIKE 'sms%'
AND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY u.id, u.email, u.name, u.softphone_number
ORDER BY sms_count DESC;
select * from teams where id = 1;
select * from roles;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1117 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES
SELECT * FROM activities WHERE uuid_to_bin('[CREDIT_CARD]-927f-4f4da2a8185c') = uuid; # 80186192 NO
SELECT * FROM crm_configurations WHERE id = 1053;
SELECT * FROM teams WHERE id = 1117;
select * from users where id = 30249;
select * from playbooks where id = 5473;
select * from playbook_categories where id = 43783;
select * from playbook_categories where playbook_id = 5473;
select * from crm_fields where id = 659242;
select * from crm_field_values where crm_field_id = 659242;
SELECT * FROM crm_field_data fd
# JOIN crm_fields f ON fd.crm_field_id = f.id
# JOIN activities a ON fd.activity_id = a.id
WHERE activity_id = 79933459
# AND f.crm_provider_id = 'hs_activity_type';
SELECT * FROM activity_messages;
select * from text_relays where created_at > '2026-05-01';
select * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;
select * from users where team_id = 1 and id IN (18608, 13934, 7160);
select * from activities where user_id = 7160 order by id desc limit 10;
select * from accounts where team_id = 1 and name = 'Column5';
select * from users where name like '%Subra%'; # 31054, 1117
select * from teams where id = 1117;
select * from activity_searches where user_id = 31054;
select * from activity_search_filters where activity_search_id IN (88882, 88902);
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.040226065,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.5006649,"top":0.07581804,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.5099734,"top":0.07581804,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.5212766,"top":0.074221864,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.52859044,"top":0.074221864,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.53723407,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.54587764,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.5568484,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.56549203,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.57413566,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.5851064,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.59607714,"top":0.074221864,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.62267286,"top":0.074221864,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.6336436,"top":0.074221864,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9587766,"top":0.074221864,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"45","depth":4,"bounds":{"left":0.9288564,"top":0.09896249,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.9411569,"top":0.09896249,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"41","depth":4,"bounds":{"left":0.95046544,"top":0.09896249,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"66","depth":4,"bounds":{"left":0.96210104,"top":0.09896249,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9740692,"top":0.09736632,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.98138297,"top":0.09736632,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2625527606738476994
|
2218652917440067151
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Code changed:
Hide
Sync Changes
Hide This Notification
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 248 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS
SELECT * FROM users where id = 24115;
SELECT * FROM accounts where id = 4002896;
SELECT * FROM teams WHERE name LIKE '%adswerve%';
SELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN ("0069N000003GIQ9QAO","0061r000019yGP9AAM","0066900001S2KWlAAN","0066900001TDpj2AAD","0066900001b8uEwAAI","0069N000001rQi0QAE","006QF00000KD40mYAD","006QF00000LzpRJYAZ","0069N000002uomtQAA","0069N000002xlMLQAY","0066900001NV6ubAAD","0061r00001HJp45AAD","006QF00000uTlUoYAK","006QF00000v0bZqYAI");
SELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203
SELECT u.id, u.email, ac.name, a.* FROM activities a
JOIN users u ON a.user_id = u.id
JOIN accounts ac ON a.account_id = ac.id
WHERE
uuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or
uuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or
uuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;
select * from users where id = 5825;
SELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;
select * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;
19594, 862
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 862 and sa.provider = 'salesforce';
select * from automated_reports where id = 36;
select ar.frequency, r.*, ar.* from automated_report_results r
join automated_reports ar on r.report_id = ar.id
where ar.frequency != 'one_off';
select s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;
select * from nudges n where n.activity_search_id
select * from teams where created_at > '2026-03-09';
SELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;
select * from users where team_id = 1 and name like '%Lukas%'; # 7160
SELECT * FROM teams WHERE id = 575;
select * from opportunities where team_id = 575;
SELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,
select * from opportunities where team_id = 1126;
SELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,
select * from opportunities where team_id = 1125;
select * from contacts c
where c.team_id = 882;
SELECT * FROM activities WHERE id = 76822967;
SELECT * FROM crm_profiles WHERE user_id = 15440;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 555;
SELECT * FROM crm_configurations WHERE id = 555;
SELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 581 and sa.provider = 'salesforce';
SELECT * FROM automated_report_results order by id desc;
select * from features;
select * from team_features where feature_id = 40;
select * from teams where id = 556;
select * from automated_reports;
where id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , ["pdf","podcast"]
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from automated_report_results order by id desc;
SELECT * FROM automated_report_results WHERE id = 1919;
select * from automated_report_results WHERE report_id = 54;
select * from opportunities where id = 7594349;
SELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - [EMAIL]
select * from playbooks where team_id = 711; # event 226147
SELECT * FROM playbook_categories WHERE playbook_id = 5515;
SELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';
SELECT * FROM crm_fields WHERE id = 226147;
SELECT * FROM crm_field_values WHERE crm_field_id = 226147;
SELECT * FROM crm_configurations WHERE id = 692;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 711 and sa.provider = 'salesforce';
SELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;
select * from leads;
select * from calendars;
SELECT
t.id AS team_id,
t.name,
LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain
FROM teams t
JOIN users u ON u.team_id = t.id
JOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'
LEFT JOIN team_domains td
ON td.team_id = t.id
AND td.deleted_at IS NULL
AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))
GROUP BY t.id, t.name, calendar_domain
ORDER BY t.name, calendar_domain;
select * from users u join calendars c on c.user_id = u.id
where u.team_id = 882;
select * from activities where id = 74049485; # team 563 crm 537
select * from activities where id = 73272382; # team 563 crm 537
select * from activities where id = 64400389; # team 563 crm 537
select * from activities where id = 58081273; # team 563 crm 537
select * from activities where id = 54520297; # team 563 crm 537
select * from participants where activity_id = 58081273;
select * from activities where crm_configuration_id = 537 and provider = 'aircall'
and account_id = 19003658 order by updated_at desc;
select * from contacts where crm_configuration_id = 537 and id = 35957759;
select * from accounts where crm_configuration_id = 537 and id = 19003658;
select * from automated_report_results where id = 1976;
select * from automated_reports where id = 583;
select * from activity_searches where id = 87714;
select * from activity_search_filters where activity_search_id = 87714;
SELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid
or uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;
SELECT * FROM crm_configurations WHERE provider = 'hubspot';
select * from rate_limits;
select * from automated_report_results where media_type = 'pdf' and status = 2
and id IN (18, 1872);
select * from automated_reports where id = 54;
SELECT * FROM users WHERE id IN (24623,29443,29613);
SELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;
select * from text_relays where created_at > '2026-05-01';
and id IN (32415, 32416);
# and id = 32412;
select * from users where team_id = 2 and email like '%scott%' and id = 29510;
SELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436
SELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses
FROM text_relays
WHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')
GROUP BY email_provider_id;
SELECT id, status, telephony_provider_id, created_at
FROM activities
WHERE id IN (80028719, 80028846);
SELECT id, status, code, email_sent_at, created_at, updated_at
FROM text_relays
WHERE id IN (32415, 32416);
SELECT id, status, code, sender, recipient, created_at
FROM text_relays
WHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'
ORDER BY created_at DESC
LIMIT 10;
SELECT id, uuid, status, code, sender, recipient, created_at, updated_at
FROM text_relays
WHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');
# [PASSWORD_DOTS]
SELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count
FROM users u
INNER JOIN activities a ON u.id = .user_id
WHERE a.type LIKE 'sms%'
AND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY u.id, u.email, u.name, u.softphone_number
ORDER BY sms_count DESC;
select * from teams where id = 1;
select * from roles;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1117 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES
SELECT * FROM activities WHERE uuid_to_bin('[CREDIT_CARD]-927f-4f4da2a8185c') = uuid; # 80186192 NO
SELECT * FROM crm_configurations WHERE id = 1053;
SELECT * FROM teams WHERE id = 1117;
select * from users where id = 30249;
select * from playbooks where id = 5473;
select * from playbook_categories where id = 43783;
select * from playbook_categories where playbook_id = 5473;
select * from crm_fields where id = 659242;
select * from crm_field_values where crm_field_id = 659242;
SELECT * FROM crm_field_data fd
# JOIN crm_fields f ON fd.crm_field_id = f.id
# JOIN activities a ON fd.activity_id = a.id
WHERE activity_id = 79933459
# AND f.crm_provider_id = 'hs_activity_type';
SELECT * FROM activity_messages;
select * from text_relays where created_at > '2026-05-01';
select * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;
select * from users where team_id = 1 and id IN (18608, 13934, 7160);
select * from activities where user_id = 7160 order by id desc limit 10;
select * from accounts where team_id = 1 and name = 'Column5';
select * from users where name like '%Subra%'; # 31054, 1117
select * from teams where id = 1117;
select * from activity_searches where user_id = 31054;
select * from activity_search_filters where activity_search_id IN (88882, 88902);
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
82983
|
NULL
|
NULL
|
NULL
|
|
82983
|
2868
|
30
|
2026-05-28T09:59:25.213770+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779962365213_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rapstomCoocKetucioWindowFV faVsco.s ~i masterproid rapstomCoocKetucioWindowFV faVsco.s ~i masterproidetTextRelayService.php© InternetMessagelnterface.phcMaenanneiservice.orclass Textkelayservacu175phavare tuncczon aororcortentchvarohtentl©Textrekysewice.oned MeetingGeneratorda Notificationên OAuth2Dn Playbooks—KeCaLA—oeownyotaeeDn Streamingla Teama Telechony#UserPilotWebhookC Abstrac Semvice cho©ActivityProviderFactory.phpCActviysemce cno@ ApiResponseService.phpg conferenceService.phgclineehCaatswies donC InstantMeetingService.php@ IntercomService.phpC IpapiClient.phpServicas+,o,ct|vaaramssconsole:ovlminnucoon nosASAHHSllocallv Аpрорconsole 1s 363 mdvASTAGINGconsoleDockerSnessage = Sservice-›users nessages-›get(Smailbox, Snessageid):Sheaders = Smessage-›getPayLoad->getHeaders®:foreach (Sheaders as Sheader)if (Sheader->name aa= *X-6n-Original-Tcl) 4Smatches = Sthis->matchesExpectedRecipient(Sheader->valve, SexpectedALias, SexpectedHost)if (l Smatches) {// Sanitize PII by removing plus-tag content for loggingSsanitizedOriginalTo = explode( separator: *+*. Sheader->value) (01:wlexwewerwceKemuscomessade'message 1d' => Snessaceld)"origanalto_sanzcized a ssanzczzedurigznallo,rexurn Smarches:Log::warning( message:'[TextRelayService) Refused message: missing X-6n-Üriginal-To header', LOutputtid jiminny.text.relaysMorowtyTQREAGI uuid (UUID with tine-low a.gB enail provider Memail_provider_id v32412 62a417Sc-48cS-42fb-bd68-f18e3513461agsuite19e1447dea629ede32413 0793823с-6386-4729-6358-54304817651₫oswite19e172856932760832414 20801368-f896-4184-8716-368653786645osunte19e1c2e118addtfcXyLS co3325ch-1744-4256-9690-48428426668gsuite1902927868964642WlhwwathwnoekCorhodtr.cohoetacotherth.gsuiteHO0DAXXoRRonAMATOT MORNOR ThEToOn-OON TEEANITRANE.gsuite19e39beeff0bd19432418 e774986d-bb2a-4ac1-9932-b6b1a7ac885:qsuite19e3a7585c7eeScc32419 [CREDIT_CARD]-8157-09927754717419c3b1b038229cedyliel noan irscediyworeschhacohostyietyOSUITG19e6e922963d45A1enail sentat2026-65-10 23:45:162826-85-11 13:89:332826-85-12 12-33:482026-05-13 18:05:8nenkoetrk terteokDenANeRe AA.DRNA2826-85-18 89:48:322826-85-18 12:42-182826-85-28 12-54:40araieTtodayTashS0TO0У L7Thu 28 May 12:59:24custonuortaraveuiosA SF jiminny@localhostHS _Jocal jiminny@localhostconsole (PROD) X& console [EU,console (STAGING= 41415 A YN72a1111•734— 735 /FUВRTx: AutoSELECT * FROM cra_field_data foPlaygroundOo jiminny045 A1 A41 У66 ^sotn chisraetost on to.cheeeto dd = tazowUocoweUNTo.cewRosd.oWHERE activity_id = 79933459*ANU T.crsprovzoera1o = "пs-аcevaсy-сyрeйTs riuh acewttiessaoosSPleesexcreays where creareo.ar020-659517select * fron activities where user_ id YN (7160, 18608) and created at > *2826-85-22' order by id descaselect * sron users where team1d=and1d01N1018688,1364.168)select * fron actávities where usen id = 7168 order by sid deso0tt8select * fron accounts where team.1d a and nane = "coluenseselect * fron users where name Like "XSubrax"; # 31054, 111/select * from teans whereds12select * fron activity_searches where user_id = 31854)salleer +Ton servity casnehi ting hend setiuity searohoiiiie roisenderDE ZOETEN Scott <[EMAIL] Fowles «Kuliiit.FoulesallovdstistintelTioence.comCharles Beatty <cbeattyfbonhanandbrook.co.ukMantoGeongtey cnanto.acorghewsiinny.comsCavan Tomay cetavan tondwlthnhony caeyHOLDSWORTH Jason <[EMAIL]:OLIVER James <janes.ol/[EMAIL] Meoan <eegan.holnes0cemardostcanv.comukas Xovnult cukas.kouaidcntninny.comI recipient ustatusMeg Katsiouras <[EMAIL] Johnston Clark Linited <447782361298.467879332268.62x7XVJ82-8txt.Jininny.comsOroreSSeKevin Wal ken <447488488754.4478539384.e05 Xamo2lxminny.comsfafler447544084583.447893937879 ARDBABYARTEYETIMInnY.COonocesserMansa Connnsiow chmbozokueto ihittneelcer lleknynrondtyimonsdomnnAraceor"61485024454.61412457749.b2qZqBEDn79txt.iminny.com* <[EMAIL]{ Raza <[EMAIL]>processedLien Callaghan <447897828347.447841358164.8017M05k2P9txt.Sininny.concatch-al1[PHONE].359877878118.18oSkdKd2M0txt.jininnv.cororocosser¿4-01 code S200snul408snut?Coun208<nulCnutcnutN Wodsud Teams 187-58 UTE-R Ai/A enano...
|
NULL
|
-7394812089810624183
|
NULL
|
visual_change
|
ocr
|
NULL
|
rapstomCoocKetucioWindowFV faVsco.s ~i masterproid rapstomCoocKetucioWindowFV faVsco.s ~i masterproidetTextRelayService.php© InternetMessagelnterface.phcMaenanneiservice.orclass Textkelayservacu175phavare tuncczon aororcortentchvarohtentl©Textrekysewice.oned MeetingGeneratorda Notificationên OAuth2Dn Playbooks—KeCaLA—oeownyotaeeDn Streamingla Teama Telechony#UserPilotWebhookC Abstrac Semvice cho©ActivityProviderFactory.phpCActviysemce cno@ ApiResponseService.phpg conferenceService.phgclineehCaatswies donC InstantMeetingService.php@ IntercomService.phpC IpapiClient.phpServicas+,o,ct|vaaramssconsole:ovlminnucoon nosASAHHSllocallv Аpрорconsole 1s 363 mdvASTAGINGconsoleDockerSnessage = Sservice-›users nessages-›get(Smailbox, Snessageid):Sheaders = Smessage-›getPayLoad->getHeaders®:foreach (Sheaders as Sheader)if (Sheader->name aa= *X-6n-Original-Tcl) 4Smatches = Sthis->matchesExpectedRecipient(Sheader->valve, SexpectedALias, SexpectedHost)if (l Smatches) {// Sanitize PII by removing plus-tag content for loggingSsanitizedOriginalTo = explode( separator: *+*. Sheader->value) (01:wlexwewerwceKemuscomessade'message 1d' => Snessaceld)"origanalto_sanzcized a ssanzczzedurigznallo,rexurn Smarches:Log::warning( message:'[TextRelayService) Refused message: missing X-6n-Üriginal-To header', LOutputtid jiminny.text.relaysMorowtyTQREAGI uuid (UUID with tine-low a.gB enail provider Memail_provider_id v32412 62a417Sc-48cS-42fb-bd68-f18e3513461agsuite19e1447dea629ede32413 0793823с-6386-4729-6358-54304817651₫oswite19e172856932760832414 20801368-f896-4184-8716-368653786645osunte19e1c2e118addtfcXyLS co3325ch-1744-4256-9690-48428426668gsuite1902927868964642WlhwwathwnoekCorhodtr.cohoetacotherth.gsuiteHO0DAXXoRRonAMATOT MORNOR ThEToOn-OON TEEANITRANE.gsuite19e39beeff0bd19432418 e774986d-bb2a-4ac1-9932-b6b1a7ac885:qsuite19e3a7585c7eeScc32419 [CREDIT_CARD]-8157-09927754717419c3b1b038229cedyliel noan irscediyworeschhacohostyietyOSUITG19e6e922963d45A1enail sentat2026-65-10 23:45:162826-85-11 13:89:332826-85-12 12-33:482026-05-13 18:05:8nenkoetrk terteokDenANeRe AA.DRNA2826-85-18 89:48:322826-85-18 12:42-182826-85-28 12-54:40araieTtodayTashS0TO0У L7Thu 28 May 12:59:24custonuortaraveuiosA SF jiminny@localhostHS _Jocal jiminny@localhostconsole (PROD) X& console [EU,console (STAGING= 41415 A YN72a1111•734— 735 /FUВRTx: AutoSELECT * FROM cra_field_data foPlaygroundOo jiminny045 A1 A41 У66 ^sotn chisraetost on to.cheeeto dd = tazowUocoweUNTo.cewRosd.oWHERE activity_id = 79933459*ANU T.crsprovzoera1o = "пs-аcevaсy-сyрeйTs riuh acewttiessaoosSPleesexcreays where creareo.ar020-659517select * fron activities where user_ id YN (7160, 18608) and created at > *2826-85-22' order by id descaselect * sron users where team1d=and1d01N1018688,1364.168)select * fron actávities where usen id = 7168 order by sid deso0tt8select * fron accounts where team.1d a and nane = "coluenseselect * fron users where name Like "XSubrax"; # 31054, 111/select * from teans whereds12select * fron activity_searches where user_id = 31854)salleer +Ton servity casnehi ting hend setiuity searohoiiiie roisenderDE ZOETEN Scott <[EMAIL] Fowles «Kuliiit.FoulesallovdstistintelTioence.comCharles Beatty <cbeattyfbonhanandbrook.co.ukMantoGeongtey cnanto.acorghewsiinny.comsCavan Tomay cetavan tondwlthnhony caeyHOLDSWORTH Jason <[EMAIL]:OLIVER James <janes.ol/[EMAIL] Meoan <eegan.holnes0cemardostcanv.comukas Xovnult cukas.kouaidcntninny.comI recipient ustatusMeg Katsiouras <[EMAIL] Johnston Clark Linited <447782361298.467879332268.62x7XVJ82-8txt.Jininny.comsOroreSSeKevin Wal ken <447488488754.4478539384.e05 Xamo2lxminny.comsfafler447544084583.447893937879 ARDBABYARTEYETIMInnY.COonocesserMansa Connnsiow chmbozokueto ihittneelcer lleknynrondtyimonsdomnnAraceor"61485024454.61412457749.b2qZqBEDn79txt.iminny.com* <[EMAIL]{ Raza <[EMAIL]>processedLien Callaghan <447897828347.447841358164.8017M05k2P9txt.Sininny.concatch-al1[PHONE].359877878118.18oSkdKd2M0txt.jininnv.cororocosser¿4-01 code S200snul408snut?Coun208<nulCnutcnutN Wodsud Teams 187-58 UTE-R Ai/A enano...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
82982
|
2867
|
14
|
2026-05-28T09:59:23.719427+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779962363719_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"master, menu","depth":5,"on_screen":true,"help_text":"Git Branch: master<br/>Some incoming commits are not fetched<br/>","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8243381250999052583
|
-8204424741936591934
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
master, menu
Start Listen Project: faVsco.js, menu
master, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
SlackFileEditViewGoHistoryWindowHelpDOCKE!DOCKER881DEV (-zsh)О ₴2-zshscreenpipe"DOCKER (-zsh)2c55fe91ca4148a230e32eaa1865e" "$?") › '/dev/null' 2>&1 &docker_lamp_12026-05-28 09:13:57 Running ['artisan' jiminny:transcription:retry-fai] No failed transcriptionsdocker_lamp_1docker_lamp_125 Doting Hubpot journal polling service... Kdocker_lamp_11 '/usr/local/bin/php' 'artisan'jiminny:transcription:retry-failed >2>&1docker_lamp_12026-05-28 09:14:18 Running ['artisan'crm: reset-governor].......21docker_lamp_11 4 '/usr/local/bin/php' 'artisan'crm:reset-governor › '/proc/1/fd/1' 2:Gracefully Stopping...press Ctrl+C again to forceContainer docker-blackfire-1 StoppingContainer docker-mariadb-1 StoppingContainer kibana StoppingContainer docker_lamp_1 StoppingContainer docker-jiminny_ext-1 StoppingContainer ngrok StoppingContainer docker-datadog-1StoppingContainer docker-datadog-1StoppedContainer docker-blackfire-1 StoppedContainer kibana StoppedContainer elasticsearch StoppingContainer docker-jiminny_ext-1 StoppedContainer elasticsearch Stoppedmariadb-11 2026-05-28ownngrokpReq="{err: ‹nil>9:14:50 0 [Note] mariadbd (initiated by: unknown): Normal sht=2026-05-28T09:14:50+0000 lvl=info msg="received stop request" obj=apprestart:false}"2026-05-289:14:50 0 [Note] InnoDB: FTS optimize threadt=2026-05-28T09:14:50+0000 lvl=info msg="session closing" obj=tunnels.set=2026-05-28T09:14:50+0000 lvl=info msg="accept failed"obj=csess id=a35.err="reconnecting session closed"Container docker_lamp_1 ErrorError while StoppingContainer ngrok Error Error while StoppingContainer docker-mariadb-1 Error Error while Stoppingerror during connect: Post "[URL_WITH_CREDENTIALS] ~/jiminny/infrastructure/dev/docker (develop) $ED→HomeDMsActivityFilesLaterMore+Jiminny …..scnicrat# happy_birthday& infosec_internal_all# infra-changes# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...° Direct messages&o lliyana Netseva€. Vasil VasilevPetko KashinskiP. Galya Dimitrova&. Stefka Stoyanova&: Todor StamatovRo Steliyan Georgiev@ Ves8. MiraRio Nikolay YankovR. Stoyan Tomovdo James Graham100% C8• Thu 28 May 12:59:23Describe what you are looking for®# releases8 226 0• MessagesC Files• Bookmarks@ytunnyrappAaueaoy GitnuoToday ~CircleCI APP 11:16 MIVTDeployment Successful!+Project: appWhen:05/28/202608:16:27Tag:View JobGitHub APP12:27 PM3 new commits pushed to master by LakyLakda1cb1d1 - JY-20915 fix missing header71898ad0 - Merge branch 'master' into JY-20915-fix-missing-header-text-relaybc8d03d9 - Merge pull request #12136 fromjiminny/JY-20915-fix-missing-header-text-relayjiminny/app | Added by GitHubNewCircleCI APP 12:53 PMDeployment Successful!Project: appWhen:05/28/202609:53:14Tag:View JobMessage #releases+..•...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81662
|
2835
|
21
|
2026-05-28T08:35:30.550992+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957330550_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7635200922161528077
|
-4598385934329243181
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
rapstomViewCoocKelucionRurTOOI-WindowFV faVsco.|s ~$ JY-20915-fix-mlproidetMpapi.ohopip console.phophp customer aol.ohophp emoedded.ohophp heaith.ohophp scim.ohophp woro ected-web.ohophp web ohopho wenhookohoseno'svsMadd→ damanar→[EMAIL]= custom.log= hubspot-journal-pollllogIdraveios<B phpunit.xmos tttisEoauth-private.keyE oauth-public.kevВА кoragoE supervisord.pidtext-relav.isoni tests> @n Feature> Ca Intearation> Ôa Services› En StubsvUniaActionsa componentaconticurationuconsoleiMcontractsleiniomainTettsatmsEventsMsycaotionMThrtutheD GuardsMHolnareD HttpMlintoarationeMlintoractianeMiloheheaYowelhe nomisKerodtoh© SyncMailbox.phpockhrhtt©TextReiayServiceTest.phgcass Textkelayservacu175pravate tuncczon asporcortentenv.ronnenttНананкРВВВВНВКЕВРВВВВВНВSnessage = Sservice-›users nessages-›get(Smailbox, Snessageld)Sheaders = Smessage-›getPayLoad->getHeaders®:sorzeanallo a nuetsco - nullforeach (Sheaders as Sheader)if (Sheader->name aa= "X-6n-Original-To') {sorzoznallo & sheader»>value} elseif (Sheader->nane aa= "To')oemesuersvallueSif (Sceciotent la= null) €Snatches = Sthis->natches axoectedbectintent Srecio tent, Sexoectedabins. Sexoectedhostsidsmatches)/I Sanitize Pll by renoving plus-tag content for loggingSsanitizedRecipient = explode( separator: "+', Srecipient) (0):Log: :info( message: "[TextRelayService) Refused message','message id' =› Snessageld,'orsoinal to saniitazed' 8 Scantitai zedRecsinhientreturn Smatches:Log::warning message:' (TextRelayService) Refused message: missing X-Gn-Original-To and To headers'."nessage id' => SmessageidDA} catch (Exception Se)Log::error( message: '(TextRelayService) Fafled to inspect message'. ("aessaoeo = smessage.oexcepczon = se->gechessage oentny?conuuraeycrodons"rerur thiteonivate function natchesEynectedPecinient(strina Srecinient strina SexoectedAlias. strina SexoectedHost)= booiA1A1S [IBAN]—214=21s216BEBCEВKhosean!=282233236238TEERORdBRBS100% 142-• Thu 28 May 11:35:30laravellog XSF jiminny@localhostA HS_local (jiminny@localhost& console (PROD.de console (EU)#COntOA STAGINGI12826-85-28 88:28:2211 10001,NOTTCE: Calendar sync end R"retrieved calendars":31,"processed calendars":3} 1"correlation_10*:~4980tCt1-082C-4660-8191-2+571C0tІУУIHIWWEIEMTONSO tAtORanGSTOnNano RACUNMeEONyLUSaCeon COnnanoIE MCOmmAnG MACa tANGAORSynO FE MAROnV:PLORA NORManO GHTIRCR:P(2026-05-28 08:28:22) Local. INFO:[SocialAccountService] Fetching token {"socialAccountId":1115,"provider":"google*} {"correlation_id*:*9436b8cd-f0cc-4ee2-805e-472888fd5928(2826-85-28 88:28:221 10c02, 7NF0:Sochau.ccountServ.celtoken retrrevedsocial.ccountidtaas"orovden"."aoog.ecorrelation.sd.9usco8cd--8cc-4002-8850-47788860597[2026-85-28 88:28:22)LencryptedTokenHanager, Generating access token. 1'mode":"Legacy"} 1"correlation_1d*: 9436b8cd-f8cc-4ee2-885e-472888f05928", "trace_1d : 19876-85-2 8332832211[Calendarl Processing sync (*calendarid*:*26760b6d-f860-427e-bf78-591e388e3cle" •fron"snult, "to":null,*delta*-*CJ x49033070EJ x49031070GAU W[2026-85-28 88:28:22] Loca2.WARNING: [Pipedrive) Account not connected for user ("userId":"e6538737-e704-455f-a37a-3e79b665a220", "account": (*Jininny| \Models| (SocialAccount"17876-85-28 8382882221Loco TEDK[CrnOwnerResolver) Integration ouner is not connected, attempting team members 1 crn_provider":"pipedrive", crn_owner":241,"tean_1d":19)[2026-05-28 08:28:22] Locar. INFO:[CrnOwnerResolver) No tean nenbers found with active cra connection 1"crm_provider":"pipedrive", "team_1d":19) 1"correlation_id":"9436b8cd-17826-85-28 88-2882221Loc0TNE0KEcononmerkesolvenlNo ream memben found mrthusetive com commectoionleem moysdenoinedo venem503092Leoma aoond""9LRohReds(2026-85-28 88:28:22] Zocal.WARNING: [Calendar) CRM disconnected for user so events will not be matched {"provider":"pipedrive", "user_id":241, "nessage": "Your Pipedrive acoSoczalAccountService) Fetching token {"socialAccount.d":1115, "provider":"google y 1"correlation_1d:*9436b8cd-f8cc-4002-885e-472888fd592:SoczalAccountService) Token retrieved {socialAccount.d":1115, "providen":"google"y 1"correlation_id*:*9436b8cd-f0cc-4002-885e-472888fd592[EncryptedTokenManager) Generating access token. {"node":"legacy"} {"cornelation_id": 943608cd-f0cc-4ce2-885c-472888fd5928", "trace_id":"19(2826-85-28 08:28:23) Loca2.INFO:Google Calendar) Failed to watch channel for calendar "calendarid":"2676cbod-f86c-427e-bf78-591e388e3cle*, "code":480,"reason":"*donainl*: \'global\*.message\": \*WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\*|"codel *: 499)|"nessagel *: |*WebHook callback nust be HTTPS:/webhook/calendar/coocle?resourceTvpezeventl}»} ("coccelatzion{₫":"9436b8сd~{8cс~4ee2-805e~4ỹ2888fđ5928"_"†cace…đ*•"19e28₫q3~о2ß4~446n~q81e~568f25₫₫đ9£g"](2826-85-28 88:28:231 10601, WARNING: [Calendanl Sunc fafled ("calendarid*:26760660-f86c-427e-bf78-5910388e301e\"reason\": \"push.webhookUrlNotHttps\",(Pnesange|": |-KebHook callback nust be HTTPS: /mebhook/callendar/coogle?nesounceTypezevent\*"codel": 489|"nossaael": |-HcbHook callback nust be HTTPS: /wehhook/calendar/aooale?cesounceTvpezeventle}*} {"correlation id:*9436b0cd-f0cc-4e62-805e-472888(d5928*, "trace id":*19e20da3-a204-446a~a01e-S68f25ddd9fd™)MANAHACTNR AR.DRODR AAA TNET(2026-05-28 08:28:23] Local. INFO:SocialAccountService) Token retrieved "socialAccountid":1421,"provider":"office" *correlation1d*:*82ba6688-7d5c-4789-9154-9918f63e2b:12826-85-28 88:28:23 Local.INF0: EncryptedTokenManager) Generating access token. :mode":"Leлacy") "connelation 2d:*82ba6688-7dSc-4789-9154-9918f63e2bfd*, "trace id":"1(2026-05-28 08:28:23) Local. INFO: [Calendar] Processing sync ('calendarid":"9e8b1a2c-1a8f-42bd-b161-810fc0baf540*, "fron":nutz, "to" :nutl, "delta":"ROusncdvaMuzCBYV8hguCBhf4uKAOnAHAGne ARIDRIRI NAA TuSArCAaalAnsAInt Comsnol CotAhind tAhon eeAAiSl AAAduntTAr:100 "nndlsdonkrThenAter TECAnnOlatIAnTRRICORhEARORTACA.1R0-01S/00196/260h.(2026-85-28 88:28:23] Local. INFO:menkras, ne gerneantll taant Tusor(2826-85-28 88:28:23] Local. INFO:mnank as, ne pecneantll taAnt TusorSocialAccountService) Token retrieved "socialAccountid":1499, "providen":"hubspot") "correlation 1d*:*82ba6688-7d5c-4789-9154-9918f63e2t[EncryptedTokenManager] Generating access token. ("node":"Legacy"} {"correlation id•OЛHARAдO, ПAGA MRO,015/001еЕторНЕни вслоло ЗаН,-Л0[CrnOwnerResolver) Integration ouner matched as CRM Ouner ("crm provider":"hubspot" "crn ouner":89, "tean id":2} ("correlation id":"82ba66:TMsnestonalondoalSiznainadnttz.cunc foc.dniinode/eonlnndnalilo loneliaos Aoes tabahhsa eanschinesineAeooootatzlon 2an.1О0hSseeEnank og, ne dechoroAAl TAAnt TuSOrJininny Console\Commands\Connand::run Memony usage before starting command {"conmand":"meeting-bot:schedule-bot" "memoryBeforeComnandInMb"Maankng, ne pechorogll TAAnt TusOr(ScheduleBotCommand) Dispatched activities to capture ("count":0} {"correlation id":*86a65984-a9f8-43c9-bBc3-1e9c8b4b9541" "trace id":*808(2826-85-28 88:29:851 10c02, INE0: Jfinfinnyl Consolel Cornands| Connandetrun Mesony usage fon connand ("cominerneeetnoaooscheouleetotrorstrorelonosnhoob.uenenonStr:kUhto%t4 spad...
|
81660
|
NULL
|
NULL
|
NULL
|
|
81661
|
2834
|
15
|
2026-05-28T08:35:30.445722+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957330445_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7635200922161528077
|
-4598385934329243181
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
iTerm2ShellEditViewSessionScriptsProfilesWindowHelp‹$0A-zshscreenpipe"DOCKER₴81DEV (docker)worker-calendar:worker-calendar_00:startedworker-conferences:worker-conferences_00: startedworker-crm-sync:worker-crm-sync_00: startedworker-crm-update:worker-crm-update_00: startedworker-download:worker-download_00:startedworker-emails:worker-emails_00:startedworker-es-update:worker-es-update_00:startedworker-nudges:worker-nudges_00: started₴2-zshО 84-zshWhat's next:Try Docker Debug forseamless, persistentdebugging tools in any container or image → docker debug docker_lamp_1Learnmoreat [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.php-v--using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5698/5698 C80100%*5ec2-user@ip-10-30-1...O 86100% <78• Thu 28 May 11:35:30181ec2-user@ip-10-30-140-...$7Fixed 0 of 5698 files in 52.731 seconds, 799.06 MB memory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $D...
|
81659
|
NULL
|
NULL
|
NULL
|
|
81619
|
2832
|
23
|
2026-05-28T08:33:07.450520+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957187450_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
2 files committed
JY-20915 fix missing header
text 2 files committed
JY-20915 fix missing header
text/html
text/html
text/html
Edit Commit Message…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
103
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {"count":0} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring start {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring end {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {"host":"docker_lamp_1"} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {"host":"docker_lamp_1","processed":0} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"calendar:sync","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1393,"provider":"google","refreshToken":"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1387,"provider":"google","refreshToken":"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1348,"provider":"google","refreshToken":"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1361,"provider":"google","refreshToken":"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1310,"provider":"google","refreshToken":"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1333,"provider":"google","refreshToken":"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1368,"provider":"google","refreshToken":"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1365,"provider":"google","refreshToken":"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1364,"provider":"google","refreshToken":"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1370,"provider":"office","refreshToken":"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:18Z\",\"trace_id\":\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\",\"correlation_id\":\"70bc0a6f-1565-4e74-94dc-419d94108fa9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1202,"provider":"office","refreshToken":"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:19Z\",\"trace_id\":\"d3d14dfc-1b70-40c4-b9db-fab12f748300\",\"correlation_id\":\"4c5f746c-8366-44c1-8733-6877607826db\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {"calendar_id":501} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1300,"provider":"google","refreshToken":"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1409,"provider":"google","refreshToken":"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1352,"provider":"google","refreshToken":"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1296,"provider":"office","refreshToken":"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","from":null,"to":null,"delta":"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=","last_sync":"2024-12-09 07:12:53","dateMode":"daily"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {"crm_provider":"integration-app","crm_owner":1695,"team_id":3143} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:20Z\",\"trace_id\":\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\",\"correlation_id\":\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":391,"provider":"office","refreshToken":"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:21Z\",\"trace_id\":\"587224ad-f597-4371-b2ba-00fcd2da1b00\",\"correlation_id\":\"4e752610-95b1-4606-847f-68e00f90be0a\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1271,"provider":"office",...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"2 files committed","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"JY-20915 fix missing header","depth":3,"on_screen":true,"value":"JY-20915 fix missing header","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Edit Commit Message…","depth":2,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"103","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring start {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring end {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1393,\"provider\":\"google\",\"refreshToken\":\"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1387,\"provider\":\"google\",\"refreshToken\":\"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1348,\"provider\":\"google\",\"refreshToken\":\"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1361,\"provider\":\"google\",\"refreshToken\":\"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1310,\"provider\":\"google\",\"refreshToken\":\"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1333,\"provider\":\"google\",\"refreshToken\":\"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1368,\"provider\":\"google\",\"refreshToken\":\"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1365,\"provider\":\"google\",\"refreshToken\":\"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1364,\"provider\":\"google\",\"refreshToken\":\"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1370,\"provider\":\"office\",\"refreshToken\":\"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:18Z\\\",\\\"trace_id\\\":\\\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\\\",\\\"correlation_id\\\":\\\"70bc0a6f-1565-4e74-94dc-419d94108fa9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1202,\"provider\":\"office\",\"refreshToken\":\"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:19Z\\\",\\\"trace_id\\\":\\\"d3d14dfc-1b70-40c4-b9db-fab12f748300\\\",\\\"correlation_id\\\":\\\"4c5f746c-8366-44c1-8733-6877607826db\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {\"calendar_id\":501} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1300,\"provider\":\"google\",\"refreshToken\":\"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1409,\"provider\":\"google\",\"refreshToken\":\"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1352,\"provider\":\"google\",\"refreshToken\":\"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1296,\"provider\":\"office\",\"refreshToken\":\"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"from\":null,\"to\":null,\"delta\":\"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=\",\"last_sync\":\"2024-12-09 07:12:53\",\"dateMode\":\"daily\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"integration-app\",\"crm_owner\":1695,\"team_id\":3143} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:20Z\\\",\\\"trace_id\\\":\\\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\\\",\\\"correlation_id\\\":\\\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":391,\"provider\":\"office\",\"refreshToken\":\"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"587224ad-f597-4371-b2ba-00fcd2da1b00\\\",\\\"correlation_id\\\":\\\"4e752610-95b1-4606-847f-68e00f90be0a\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1271,\"provider\":\"office\",\"refreshToken\":\"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd8bf2a7-bc49-43d7-a487-892c51e27600 Correlation ID: 51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"dd8bf2a7-bc49-43d7-a487-892c51e27600\\\",\\\"correlation_id\\\":\\\"51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1351,\"provider\":\"google\",\"refreshToken\":\"4271d15b9e60a606439caddc68337f783e472c85b03dacff14d1b6dfded9051c\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1366,\"provider\":\"google\",\"refreshToken\":\"ae21385059b2eebfd43f68aecd56eccd702a1aabb6598f1f7ab594ed8af491b4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":378} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":504} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.NOTICE: Calendar sync end {\"retrieved_calendars\":31,\"processed_calendars\":3} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [Calendar] Processing sync {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"from\":null,\"to\":null,\"delta\":\"CJ_x49O3jpIDEJ_x49O3jpIDGAUgw67KlwMow67KlwM=\",\"last_sync\":\"2026-01-19 07:48:40\",\"dateMode\":\"daily\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Pipedrive] Account not connected for user {\"userId\":\"e6538737-e7b4-455f-a37a-3e79b665a220\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":1116,\"sociable_id\":241,\"provider_user_id\":\"19555731\",\"expires\":1779091997,\"refresh_token_expires\":null,\"provider\":\"pipedrive\",\"state\":\"full-refresh\",\"auth_scope\":\"base,deals:full,activities:full,contacts:full,search:read\",\"retry_after\":null,\"created_at\":\"2023-09-08 09:44:29\",\"updated_at\":\"2026-05-18 08:13:32\"}}} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"pipedrive\",\"crm_owner\":241,\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Calendar] CRM disconnected for user so events will not be matched {\"provider\":\"pipedrive\",\"user_id\":241,\"message\":\"Your Pipedrive account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Calendar] Processing sync {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\",\"from\":null,\"to\":null,\"delta\":\"R0usmcdvmMuZCBYV0hguCBhf4uKqyU9_gdNd-le_nqqau95XAUmZwlIAy2uwtCf5sA67w6NIiDvawUSmVjpTzZO-RsxLdeS-g8Kxy6ODZQxAxafq8AJNx0hJV7T291NUvfaPYqLMv-3je3IdhAPUtXQXkHtYaBAlX_DDBxwc3zYoVVQ8iM9mQkBykdA3sh-KVYPyzi7nK4cZg5Jzpu9tHA.UA7urx3pJyhUhdo_16STIbSNXUrF-qeQVIis9stVUeY\",\"last_sync\":\"2026-05-28 07:44:06\",\"dateMode\":\"daily\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [MS Office Calendar] Skipping delta sync for daily mode {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:29:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring start {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring end {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring start {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring end {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Starting sync {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"expected_alias\":\"catch-all\",\"expected_host\":\"txt.staging.jiminny.com\"} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Sync completed {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"messages_processed\":0,\"message_ids\":[]} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Running pre-meeting notification command {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Running conference:monitor:start command for activities in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: [conference:monitor:start] No activities found in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesEnded {\"from\":\"08:25\",\"to\":\"08:30\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesWithUnfinishedSession {\"from\":\"22:20\",\"to\":\"22:25\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:23] local.NOTICE: Repairing HubSpot tokens start {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: Trying to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":59,\"provider\":\"hubspot\",\"refreshToken\":\"97b78f6e2cc49965c00c2492b602b02708b1392551e6b3f113fbaa48992af90b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.ERROR: Failed to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: Trying to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":306,\"provider\":\"hubspot\",\"refreshToken\":\"6fa6aa8cc641d131231acc3470f5c03cb3b07b2e580fb18f8acb3b1dbb72549b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: Trying to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1372,\"provider\":\"hubspot\",\"refreshToken\":\"9aa73948c761da29dce46c177cf9aee1fde483a44169ca38723f9f0597d7a8c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.NOTICE: Repairing HubSpot tokens end {\"total\":3,\"fixed\":0,\"failed\":3} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Command] Starting polling service {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Service starting {\"memory_limit\":\"256M\",\"max_execution_time\":\"0\",\"initial_memory_mb\":62.0} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Acquired polling lock {\"expires_at\":\"2026-05-28T08:32:33.444809Z\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814238,\"provider\":\"twilio-flex\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814239,\"provider\":\"xant\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814240,\"provider\":\"apollo\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814241,\"provider\":\"groove\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814242,\"provider\":\"twilio-video\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814243,\"provider\":\"hubspot\",\"team\":\"hubspot\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.WARNING: [Salesforce] Account not connected for user {\"userId\":\"cdf8b554-d951-4758-bc2b-c1b85d1cd0b9\",\"account\":null} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"salesforce\",\"crm_owner\":3,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] TeamMember found with active crm connection {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SyncActivity] Start {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.NOTICE: [TwilioFlex] Calls import start {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.ALERT: [SyncActivity] Failed {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"[HTTP 401] Unable to fetch page: Authenticate\",\"file\":\"/home/jiminny/vendor/twilio/sdk/src/Twilio/Page.php\",\"line\":60} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SyncActivity] Start {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT Playbooks_Call_Date__c,Playbooks_Call_Recording__c,CreatedDate,TaskSubtype,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+Playbooks_Call_Date__c%2CPlaybooks_Call_Recording__c%2CCreatedDate%2CTaskSubtype%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [Xant (InsideSales)] No calls found. {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24080216,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT AccountId,CreatedDate,TaskSubtype,CallType,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+AccountId%2CCreatedDate%2CTaskSubtype%2CCallType%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Apollo] No calls found. {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24242184,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT call_recording_url__c,TaskSubtype,CreatedDate,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.ERROR: [Salesforce] Request exception [400] \nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. {\"url\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000\",\"data\":{\"headers\":{\"Authorization\":\"Bearer 00D2g0000008hH4!AQEAQHWUK6nshi8dSCX9CJphxkVivcv_TK98TLOckVy4i0Z1gQfAoRRuH2LVwDXDkbTPs80wvQjczjAlOz0UEtbHoORBLi2u\"}},\"response\":{\"GuzzleHttp\\\\Psr7\\\\Stream\":\"[{\\\"message\\\":\\\"\\\\nSELECT call_recording_url__c,TaskSubtype\\\\n ^\\\\nERROR at Row:1:Column:8\\\\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\\\",\\\"errorCode\\\":\\\"INVALID_FIELD\\\"}]\"},\"fields\":[]} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.ALERT: [SyncActivity] Failed {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"\nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\",\"file\":\"/home/jiminny/app/Services/Crm/Salesforce/Client.php\",\"line\":564} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"SELECT Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type,twilio_call_sid__c,Lead_UUID__c,Opportunity__c\n FROM Task\n WHERE Type = 'Video'\n AND isClosed = true\n AND IsDeleted = false\n AND LastModifiedDate >= :from\n AND twilio_call_sid__c != NULL AND LastModifiedDate <= :to ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=SELECT+Id%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%2Ctwilio_call_sid__c%2CLead_UUID__c%2COpportunity__c%0A++++++++++++++FROM+Task%0A++++++++++++WHERE+Type+%3D+%27Video%27%0A++++++++++++++AND+isClosed+%3D+true%0A++++++++++++++AND+IsDeleted+%3D+false%0A++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A++++++++++++++AND+twilio_call_sid__c+%21%3D+NULL+AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z+ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [Twilio Video] No calls found. {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24634032,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Start {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [HubSpot] Search calls for period {\"from\":\"2026-05-28 08:14:00\",\"to\":\"2026-05-28 08:30:00\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2,\"memory_usage\":24947696,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] starting. {\"playlists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] finished. {\"normalizedPlaylists\":[],\"deletedPlaylists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring start {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring end {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:23] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"usage\":22563136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":148,\"team_id\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Syncing opportunities using strategy: lastModified {\"team\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [Hubspot] Pagination completed {\"team_id\":2,\"endpoint\":\"https://api.hubapi.com/crm/v3/objects/deals/search\",\"total_requests\":1,\"total_records_fetched\":0,\"total_elapsed_seconds\":0.4,\"average_seconds_per_request\":0.4} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Synced opportunities {\"team\":2,\"strategies\":\"lastModified\",\"sync_count\":0,\"total\":0,\"last_synced_id\":null,\"duration_ms\":432.6} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"provider\":\"hubspot\",\"status\":\"completed\",\"duration_ms\":543.02,\"usage\":22983640,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"usage\":22961848,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"2ac0447f-3c8c-4ce0-baeb-b63ddb76fa9b\",\"account\":null} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":130,\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":23.85,\"usage\":23024000,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"usage\":22984760,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"33e34a7a-1c02-4f04-87ac-22c3a385e6e3\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":306,\"sociable_id\":109,\"provider_user_id\":\"11348452\",\"expires\":1701077403,\"refresh_token_expires\":null,\"provider\":\"hubspot\",\"state\":\"full-refresh\",\"auth_scope\":null,\"retry_after\":null,\"created_at\":\"2020-09-01 16:59:04\",\"updated_at\":\"2023-11-27 09:30:03\"}}} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":109,\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":14.98,\"usage\":23047624,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Your HubSpot account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Service ending {\"runtime_seconds\":56,\"total_cycles\":5,\"files_downloaded\":0,\"empty_files\":0,\"other_portal_skipped\":0,\"total_events\":0,\"events_per_file\":0,\"avg_api_ms\":192.1,\"avg_download_ms\":0.0,\"avg_transform_ms\":0.0,\"avg_process_ms\":0.0,\"peak_memory_mb\":99.88} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Released polling lock {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"usage\":23005136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"71e3aac5-fb66-47c5-a236-2d051ae3e319\",\"account\":null} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":256,\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":34.51,\"usage\":23021248,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring start {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring end {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] STARTING batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] FINISHED batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:25] local.INFO: [Jiminny\\Jobs\\Mailbox\\CreateBatches] processed 1 inboxes and created 0 batches {\"userId\":null,\"batchSize\":30,\"maxBatches\":1000} {\"correlation_id\":\"e60597ef-aca8-4bda-bb90-18f01e96874d\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}","depth":4,"on_screen":true,"value":"[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring start {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring end {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1393,\"provider\":\"google\",\"refreshToken\":\"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1387,\"provider\":\"google\",\"refreshToken\":\"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1348,\"provider\":\"google\",\"refreshToken\":\"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1361,\"provider\":\"google\",\"refreshToken\":\"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1310,\"provider\":\"google\",\"refreshToken\":\"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1333,\"provider\":\"google\",\"refreshToken\":\"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1368,\"provider\":\"google\",\"refreshToken\":\"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1365,\"provider\":\"google\",\"refreshToken\":\"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1364,\"provider\":\"google\",\"refreshToken\":\"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1370,\"provider\":\"office\",\"refreshToken\":\"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:18Z\\\",\\\"trace_id\\\":\\\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\\\",\\\"correlation_id\\\":\\\"70bc0a6f-1565-4e74-94dc-419d94108fa9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1202,\"provider\":\"office\",\"refreshToken\":\"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:19Z\\\",\\\"trace_id\\\":\\\"d3d14dfc-1b70-40c4-b9db-fab12f748300\\\",\\\"correlation_id\\\":\\\"4c5f746c-8366-44c1-8733-6877607826db\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {\"calendar_id\":501} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1300,\"provider\":\"google\",\"refreshToken\":\"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1409,\"provider\":\"google\",\"refreshToken\":\"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1352,\"provider\":\"google\",\"refreshToken\":\"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1296,\"provider\":\"office\",\"refreshToken\":\"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"from\":null,\"to\":null,\"delta\":\"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=\",\"last_sync\":\"2024-12-09 07:12:53\",\"dateMode\":\"daily\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"integration-app\",\"crm_owner\":1695,\"team_id\":3143} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:20Z\\\",\\\"trace_id\\\":\\\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\\\",\\\"correlation_id\\\":\\\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":391,\"provider\":\"office\",\"refreshToken\":\"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"587224ad-f597-4371-b2ba-00fcd2da1b00\\\",\\\"correlation_id\\\":\\\"4e752610-95b1-4606-847f-68e00f90be0a\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1271,\"provider\":\"office\",\"refreshToken\":\"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd8bf2a7-bc49-43d7-a487-892c51e27600 Correlation ID: 51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"dd8bf2a7-bc49-43d7-a487-892c51e27600\\\",\\\"correlation_id\\\":\\\"51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1351,\"provider\":\"google\",\"refreshToken\":\"4271d15b9e60a606439caddc68337f783e472c85b03dacff14d1b6dfded9051c\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1366,\"provider\":\"google\",\"refreshToken\":\"ae21385059b2eebfd43f68aecd56eccd702a1aabb6598f1f7ab594ed8af491b4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":378} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":504} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.NOTICE: Calendar sync end {\"retrieved_calendars\":31,\"processed_calendars\":3} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [Calendar] Processing sync {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"from\":null,\"to\":null,\"delta\":\"CJ_x49O3jpIDEJ_x49O3jpIDGAUgw67KlwMow67KlwM=\",\"last_sync\":\"2026-01-19 07:48:40\",\"dateMode\":\"daily\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Pipedrive] Account not connected for user {\"userId\":\"e6538737-e7b4-455f-a37a-3e79b665a220\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":1116,\"sociable_id\":241,\"provider_user_id\":\"19555731\",\"expires\":1779091997,\"refresh_token_expires\":null,\"provider\":\"pipedrive\",\"state\":\"full-refresh\",\"auth_scope\":\"base,deals:full,activities:full,contacts:full,search:read\",\"retry_after\":null,\"created_at\":\"2023-09-08 09:44:29\",\"updated_at\":\"2026-05-18 08:13:32\"}}} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"pipedrive\",\"crm_owner\":241,\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Calendar] CRM disconnected for user so events will not be matched {\"provider\":\"pipedrive\",\"user_id\":241,\"message\":\"Your Pipedrive account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Calendar] Processing sync {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\",\"from\":null,\"to\":null,\"delta\":\"R0usmcdvmMuZCBYV0hguCBhf4uKqyU9_gdNd-le_nqqau95XAUmZwlIAy2uwtCf5sA67w6NIiDvawUSmVjpTzZO-RsxLdeS-g8Kxy6ODZQxAxafq8AJNx0hJV7T291NUvfaPYqLMv-3je3IdhAPUtXQXkHtYaBAlX_DDBxwc3zYoVVQ8iM9mQkBykdA3sh-KVYPyzi7nK4cZg5Jzpu9tHA.UA7urx3pJyhUhdo_16STIbSNXUrF-qeQVIis9stVUeY\",\"last_sync\":\"2026-05-28 07:44:06\",\"dateMode\":\"daily\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [MS Office Calendar] Skipping delta sync for daily mode {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:29:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring start {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring end {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring start {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring end {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Starting sync {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"expected_alias\":\"catch-all\",\"expected_host\":\"txt.staging.jiminny.com\"} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Sync completed {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"messages_processed\":0,\"message_ids\":[]} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Running pre-meeting notification command {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Running conference:monitor:start command for activities in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: [conference:monitor:start] No activities found in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesEnded {\"from\":\"08:25\",\"to\":\"08:30\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesWithUnfinishedSession {\"from\":\"22:20\",\"to\":\"22:25\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:23] local.NOTICE: Repairing HubSpot tokens start {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: Trying to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":59,\"provider\":\"hubspot\",\"refreshToken\":\"97b78f6e2cc49965c00c2492b602b02708b1392551e6b3f113fbaa48992af90b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.ERROR: Failed to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: Trying to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":306,\"provider\":\"hubspot\",\"refreshToken\":\"6fa6aa8cc641d131231acc3470f5c03cb3b07b2e580fb18f8acb3b1dbb72549b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: Trying to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1372,\"provider\":\"hubspot\",\"refreshToken\":\"9aa73948c761da29dce46c177cf9aee1fde483a44169ca38723f9f0597d7a8c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.NOTICE: Repairing HubSpot tokens end {\"total\":3,\"fixed\":0,\"failed\":3} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Command] Starting polling service {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Service starting {\"memory_limit\":\"256M\",\"max_execution_time\":\"0\",\"initial_memory_mb\":62.0} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Acquired polling lock {\"expires_at\":\"2026-05-28T08:32:33.444809Z\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814238,\"provider\":\"twilio-flex\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814239,\"provider\":\"xant\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814240,\"provider\":\"apollo\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814241,\"provider\":\"groove\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814242,\"provider\":\"twilio-video\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814243,\"provider\":\"hubspot\",\"team\":\"hubspot\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.WARNING: [Salesforce] Account not connected for user {\"userId\":\"cdf8b554-d951-4758-bc2b-c1b85d1cd0b9\",\"account\":null} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"salesforce\",\"crm_owner\":3,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] TeamMember found with active crm connection {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SyncActivity] Start {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.NOTICE: [TwilioFlex] Calls import start {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.ALERT: [SyncActivity] Failed {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"[HTTP 401] Unable to fetch page: Authenticate\",\"file\":\"/home/jiminny/vendor/twilio/sdk/src/Twilio/Page.php\",\"line\":60} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SyncActivity] Start {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT Playbooks_Call_Date__c,Playbooks_Call_Recording__c,CreatedDate,TaskSubtype,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+Playbooks_Call_Date__c%2CPlaybooks_Call_Recording__c%2CCreatedDate%2CTaskSubtype%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [Xant (InsideSales)] No calls found. {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24080216,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT AccountId,CreatedDate,TaskSubtype,CallType,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+AccountId%2CCreatedDate%2CTaskSubtype%2CCallType%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Apollo] No calls found. {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24242184,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT call_recording_url__c,TaskSubtype,CreatedDate,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.ERROR: [Salesforce] Request exception [400] \nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. {\"url\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000\",\"data\":{\"headers\":{\"Authorization\":\"Bearer 00D2g0000008hH4!AQEAQHWUK6nshi8dSCX9CJphxkVivcv_TK98TLOckVy4i0Z1gQfAoRRuH2LVwDXDkbTPs80wvQjczjAlOz0UEtbHoORBLi2u\"}},\"response\":{\"GuzzleHttp\\\\Psr7\\\\Stream\":\"[{\\\"message\\\":\\\"\\\\nSELECT call_recording_url__c,TaskSubtype\\\\n ^\\\\nERROR at Row:1:Column:8\\\\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\\\",\\\"errorCode\\\":\\\"INVALID_FIELD\\\"}]\"},\"fields\":[]} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.ALERT: [SyncActivity] Failed {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"\nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\",\"file\":\"/home/jiminny/app/Services/Crm/Salesforce/Client.php\",\"line\":564} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"SELECT Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type,twilio_call_sid__c,Lead_UUID__c,Opportunity__c\n FROM Task\n WHERE Type = 'Video'\n AND isClosed = true\n AND IsDeleted = false\n AND LastModifiedDate >= :from\n AND twilio_call_sid__c != NULL AND LastModifiedDate <= :to ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=SELECT+Id%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%2Ctwilio_call_sid__c%2CLead_UUID__c%2COpportunity__c%0A++++++++++++++FROM+Task%0A++++++++++++WHERE+Type+%3D+%27Video%27%0A++++++++++++++AND+isClosed+%3D+true%0A++++++++++++++AND+IsDeleted+%3D+false%0A++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A++++++++++++++AND+twilio_call_sid__c+%21%3D+NULL+AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z+ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [Twilio Video] No calls found. {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24634032,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Start {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [HubSpot] Search calls for period {\"from\":\"2026-05-28 08:14:00\",\"to\":\"2026-05-28 08:30:00\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2,\"memory_usage\":24947696,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] starting. {\"playlists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] finished. {\"normalizedPlaylists\":[],\"deletedPlaylists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring start {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring end {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:23] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"usage\":22563136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":148,\"team_id\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Syncing opportunities using strategy: lastModified {\"team\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [Hubspot] Pagination completed {\"team_id\":2,\"endpoint\":\"https://api.hubapi.com/crm/v3/objects/deals/search\",\"total_requests\":1,\"total_records_fetched\":0,\"total_elapsed_seconds\":0.4,\"average_seconds_per_request\":0.4} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Synced opportunities {\"team\":2,\"strategies\":\"lastModified\",\"sync_count\":0,\"total\":0,\"last_synced_id\":null,\"duration_ms\":432.6} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"provider\":\"hubspot\",\"status\":\"completed\",\"duration_ms\":543.02,\"usage\":22983640,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"usage\":22961848,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"2ac0447f-3c8c-4ce0-baeb-b63ddb76fa9b\",\"account\":null} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":130,\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":23.85,\"usage\":23024000,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"usage\":22984760,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"33e34a7a-1c02-4f04-87ac-22c3a385e6e3\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":306,\"sociable_id\":109,\"provider_user_id\":\"11348452\",\"expires\":1701077403,\"refresh_token_expires\":null,\"provider\":\"hubspot\",\"state\":\"full-refresh\",\"auth_scope\":null,\"retry_after\":null,\"created_at\":\"2020-09-01 16:59:04\",\"updated_at\":\"2023-11-27 09:30:03\"}}} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":109,\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":14.98,\"usage\":23047624,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Your HubSpot account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Service ending {\"runtime_seconds\":56,\"total_cycles\":5,\"files_downloaded\":0,\"empty_files\":0,\"other_portal_skipped\":0,\"total_events\":0,\"events_per_file\":0,\"avg_api_ms\":192.1,\"avg_download_ms\":0.0,\"avg_transform_ms\":0.0,\"avg_process_ms\":0.0,\"peak_memory_mb\":99.88} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Released polling lock {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"usage\":23005136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"71e3aac5-fb66-47c5-a236-2d051ae3e319\",\"account\":null} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":256,\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":34.51,\"usage\":23021248,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring start {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring end {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] STARTING batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] FINISHED batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:25] local.INFO: [Jiminny\\Jobs\\Mailbox\\CreateBatches] processed 1 inboxes and created 0 batches {\"userId\":null,\"batchSize\":30,\"maxBatches\":1000} {\"correlation_id\":\"e60597ef-aca8-4bda-bb90-18f01e96874d\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-914263408208002466
|
3613057122943418527
|
click
|
accessibility
|
NULL
|
2 files committed
JY-20915 fix missing header
text 2 files committed
JY-20915 fix missing header
text/html
text/html
text/html
Edit Commit Message…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
103
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {"count":0} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring start {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring end {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {"host":"docker_lamp_1"} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {"host":"docker_lamp_1","processed":0} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"calendar:sync","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1393,"provider":"google","refreshToken":"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1387,"provider":"google","refreshToken":"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1348,"provider":"google","refreshToken":"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1361,"provider":"google","refreshToken":"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1310,"provider":"google","refreshToken":"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1333,"provider":"google","refreshToken":"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1368,"provider":"google","refreshToken":"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1365,"provider":"google","refreshToken":"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1364,"provider":"google","refreshToken":"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1370,"provider":"office","refreshToken":"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:18Z\",\"trace_id\":\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\",\"correlation_id\":\"70bc0a6f-1565-4e74-94dc-419d94108fa9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1202,"provider":"office","refreshToken":"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:19Z\",\"trace_id\":\"d3d14dfc-1b70-40c4-b9db-fab12f748300\",\"correlation_id\":\"4c5f746c-8366-44c1-8733-6877607826db\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {"calendar_id":501} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1300,"provider":"google","refreshToken":"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1409,"provider":"google","refreshToken":"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1352,"provider":"google","refreshToken":"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1296,"provider":"office","refreshToken":"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","from":null,"to":null,"delta":"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=","last_sync":"2024-12-09 07:12:53","dateMode":"daily"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {"crm_provider":"integration-app","crm_owner":1695,"team_id":3143} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:20Z\",\"trace_id\":\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\",\"correlation_id\":\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":391,"provider":"office","refreshToken":"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:21Z\",\"trace_id\":\"587224ad-f597-4371-b2ba-00fcd2da1b00\",\"correlation_id\":\"4e752610-95b1-4606-847f-68e00f90be0a\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1271,"provider":"office",...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81618
|
2833
|
26
|
2026-05-28T08:33:07.556229+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957187556_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
2 files committed
JY-20915 fix missing header
text 2 files committed
JY-20915 fix missing header
text/html
text/html
text/html
Edit Commit Message…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"2 files committed","depth":2,"bounds":{"left":0.8753325,"top":0.91300875,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"JY-20915 fix missing header","depth":3,"bounds":{"left":0.8753325,"top":0.92897046,"width":0.11037234,"height":0.013567438},"on_screen":true,"value":"JY-20915 fix missing header","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.92897046,"width":0.05817819,"height":0.013567438},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Edit Commit Message…","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.048204787,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3441740384976428124
|
-6865794859280429614
|
click
|
accessibility
|
NULL
|
2 files committed
JY-20915 fix missing header
text 2 files committed
JY-20915 fix missing header
text/html
text/html
text/html
Edit Commit Message…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'...
|
81617
|
NULL
|
NULL
|
NULL
|
|
81617
|
2833
|
25
|
2026-05-28T08:32:41.372636+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957161372_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
remote: Resolving deltas: 100% (10/10), completed remote: Resolving deltas: 100% (10/10), completed with 10 local objects.
2 files committed
JY-20915 fix missing header
text/html
text/html
text/html
Edit Commit Message…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
103
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {"count":0} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring start {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring end {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {"host":"docker_lamp_1"} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {"host":"docker_lamp_1","processed":0} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"calendar:sync","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1393,"provider":"google","refreshToken":"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1387,"provider":"google","refreshToken":"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1348,"provider":"google","refreshToken":"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1361,"provider":"google","refreshToken":"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1310,"provider":"google","refreshToken":"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1333,"provider":"google","refreshToken":"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1368,"provider":"google","refreshToken":"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1365,"provider":"google","refreshToken":"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1364,"provider":"google","refreshToken":"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1370,"provider":"office","refreshToken":"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:18Z\",\"trace_id\":\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\",\"correlation_id\":\"70bc0a6f-1565-4e74-94dc-419d94108fa9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1202,"provider":"office","refreshToken":"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:19Z\",\"trace_id\":\"d3d14dfc-1b70-40c4-b9db-fab12f748300\",\"correlation_id\":\"4c5f746c-8366-44c1-8733-6877607826db\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {"calendar_id":501} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1300,"provider":"google","refreshToken":"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1409,"provider":"google","refreshToken":"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1352,"provider":"google","refreshToken":"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1296,"provider":"office","refreshToken":"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","from":null,"to":null,"delta":"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=","last_sync":"2024-12-09 07:12:53","dateMode":"daily"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {"crm_provider":"integration-app","crm_owner":1695,"team_id":3143} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:20Z\",\"trace_id\":\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\",\"correlation_id\":\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":391,"provider":"office","refreshToken":"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:21Z\",\"trace_id\":\"587224ad-f597-4371-b2ba-00fcd2da1b00\",\"correlation_id\":\"4e752610-95b1-4606-847f-68e00f90be0a\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Re...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"","depth":2,"bounds":{"left":0.6625665,"top":0.44134077,"width":0.06948138,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"remote: Resolving deltas: 100% (10/10), completed with 10 local objects.","depth":2,"bounds":{"left":0.6625665,"top":0.47326416,"width":0.06948138,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2 files committed","depth":2,"bounds":{"left":0.8753325,"top":0.91300875,"width":0.100398935,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXTextField","text":"JY-20915 fix missing header","depth":3,"bounds":{"left":0.8753325,"top":0.92897046,"width":0.11037234,"height":0.013567438},"on_screen":true,"value":"JY-20915 fix missing header","help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"bounds":{"left":0.8753325,"top":0.92897046,"width":0.05817819,"height":0.013567438},"on_screen":true,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"text/html","depth":4,"on_screen":false,"help_text":"text/html","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Edit Commit Message…","depth":2,"bounds":{"left":0.8753325,"top":0.9481245,"width":0.048204787,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"103","depth":4,"bounds":{"left":0.72539896,"top":0.10055866,"width":0.011968086,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring start {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring end {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1393,\"provider\":\"google\",\"refreshToken\":\"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1387,\"provider\":\"google\",\"refreshToken\":\"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1348,\"provider\":\"google\",\"refreshToken\":\"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1361,\"provider\":\"google\",\"refreshToken\":\"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1310,\"provider\":\"google\",\"refreshToken\":\"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1333,\"provider\":\"google\",\"refreshToken\":\"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1368,\"provider\":\"google\",\"refreshToken\":\"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1365,\"provider\":\"google\",\"refreshToken\":\"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1364,\"provider\":\"google\",\"refreshToken\":\"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1370,\"provider\":\"office\",\"refreshToken\":\"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:18Z\\\",\\\"trace_id\\\":\\\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\\\",\\\"correlation_id\\\":\\\"70bc0a6f-1565-4e74-94dc-419d94108fa9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1202,\"provider\":\"office\",\"refreshToken\":\"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:19Z\\\",\\\"trace_id\\\":\\\"d3d14dfc-1b70-40c4-b9db-fab12f748300\\\",\\\"correlation_id\\\":\\\"4c5f746c-8366-44c1-8733-6877607826db\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {\"calendar_id\":501} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1300,\"provider\":\"google\",\"refreshToken\":\"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1409,\"provider\":\"google\",\"refreshToken\":\"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1352,\"provider\":\"google\",\"refreshToken\":\"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1296,\"provider\":\"office\",\"refreshToken\":\"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"from\":null,\"to\":null,\"delta\":\"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=\",\"last_sync\":\"2024-12-09 07:12:53\",\"dateMode\":\"daily\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"integration-app\",\"crm_owner\":1695,\"team_id\":3143} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:20Z\\\",\\\"trace_id\\\":\\\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\\\",\\\"correlation_id\\\":\\\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":391,\"provider\":\"office\",\"refreshToken\":\"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"587224ad-f597-4371-b2ba-00fcd2da1b00\\\",\\\"correlation_id\\\":\\\"4e752610-95b1-4606-847f-68e00f90be0a\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1271,\"provider\":\"office\",\"refreshToken\":\"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd8bf2a7-bc49-43d7-a487-892c51e27600 Correlation ID: 51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"dd8bf2a7-bc49-43d7-a487-892c51e27600\\\",\\\"correlation_id\\\":\\\"51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1351,\"provider\":\"google\",\"refreshToken\":\"4271d15b9e60a606439caddc68337f783e472c85b03dacff14d1b6dfded9051c\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1366,\"provider\":\"google\",\"refreshToken\":\"ae21385059b2eebfd43f68aecd56eccd702a1aabb6598f1f7ab594ed8af491b4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":378} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":504} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.NOTICE: Calendar sync end {\"retrieved_calendars\":31,\"processed_calendars\":3} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [Calendar] Processing sync {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"from\":null,\"to\":null,\"delta\":\"CJ_x49O3jpIDEJ_x49O3jpIDGAUgw67KlwMow67KlwM=\",\"last_sync\":\"2026-01-19 07:48:40\",\"dateMode\":\"daily\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Pipedrive] Account not connected for user {\"userId\":\"e6538737-e7b4-455f-a37a-3e79b665a220\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":1116,\"sociable_id\":241,\"provider_user_id\":\"19555731\",\"expires\":1779091997,\"refresh_token_expires\":null,\"provider\":\"pipedrive\",\"state\":\"full-refresh\",\"auth_scope\":\"base,deals:full,activities:full,contacts:full,search:read\",\"retry_after\":null,\"created_at\":\"2023-09-08 09:44:29\",\"updated_at\":\"2026-05-18 08:13:32\"}}} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"pipedrive\",\"crm_owner\":241,\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Calendar] CRM disconnected for user so events will not be matched {\"provider\":\"pipedrive\",\"user_id\":241,\"message\":\"Your Pipedrive account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Calendar] Processing sync {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\",\"from\":null,\"to\":null,\"delta\":\"R0usmcdvmMuZCBYV0hguCBhf4uKqyU9_gdNd-le_nqqau95XAUmZwlIAy2uwtCf5sA67w6NIiDvawUSmVjpTzZO-RsxLdeS-g8Kxy6ODZQxAxafq8AJNx0hJV7T291NUvfaPYqLMv-3je3IdhAPUtXQXkHtYaBAlX_DDBxwc3zYoVVQ8iM9mQkBykdA3sh-KVYPyzi7nK4cZg5Jzpu9tHA.UA7urx3pJyhUhdo_16STIbSNXUrF-qeQVIis9stVUeY\",\"last_sync\":\"2026-05-28 07:44:06\",\"dateMode\":\"daily\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [MS Office Calendar] Skipping delta sync for daily mode {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:29:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring start {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring end {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring start {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring end {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Starting sync {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"expected_alias\":\"catch-all\",\"expected_host\":\"txt.staging.jiminny.com\"} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Sync completed {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"messages_processed\":0,\"message_ids\":[]} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Running pre-meeting notification command {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Running conference:monitor:start command for activities in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: [conference:monitor:start] No activities found in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesEnded {\"from\":\"08:25\",\"to\":\"08:30\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesWithUnfinishedSession {\"from\":\"22:20\",\"to\":\"22:25\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:23] local.NOTICE: Repairing HubSpot tokens start {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: Trying to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":59,\"provider\":\"hubspot\",\"refreshToken\":\"97b78f6e2cc49965c00c2492b602b02708b1392551e6b3f113fbaa48992af90b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.ERROR: Failed to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: Trying to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":306,\"provider\":\"hubspot\",\"refreshToken\":\"6fa6aa8cc641d131231acc3470f5c03cb3b07b2e580fb18f8acb3b1dbb72549b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: Trying to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1372,\"provider\":\"hubspot\",\"refreshToken\":\"9aa73948c761da29dce46c177cf9aee1fde483a44169ca38723f9f0597d7a8c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.NOTICE: Repairing HubSpot tokens end {\"total\":3,\"fixed\":0,\"failed\":3} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Command] Starting polling service {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Service starting {\"memory_limit\":\"256M\",\"max_execution_time\":\"0\",\"initial_memory_mb\":62.0} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Acquired polling lock {\"expires_at\":\"2026-05-28T08:32:33.444809Z\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814238,\"provider\":\"twilio-flex\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814239,\"provider\":\"xant\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814240,\"provider\":\"apollo\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814241,\"provider\":\"groove\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814242,\"provider\":\"twilio-video\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814243,\"provider\":\"hubspot\",\"team\":\"hubspot\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.WARNING: [Salesforce] Account not connected for user {\"userId\":\"cdf8b554-d951-4758-bc2b-c1b85d1cd0b9\",\"account\":null} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"salesforce\",\"crm_owner\":3,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] TeamMember found with active crm connection {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SyncActivity] Start {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.NOTICE: [TwilioFlex] Calls import start {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.ALERT: [SyncActivity] Failed {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"[HTTP 401] Unable to fetch page: Authenticate\",\"file\":\"/home/jiminny/vendor/twilio/sdk/src/Twilio/Page.php\",\"line\":60} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SyncActivity] Start {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT Playbooks_Call_Date__c,Playbooks_Call_Recording__c,CreatedDate,TaskSubtype,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+Playbooks_Call_Date__c%2CPlaybooks_Call_Recording__c%2CCreatedDate%2CTaskSubtype%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [Xant (InsideSales)] No calls found. {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24080216,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT AccountId,CreatedDate,TaskSubtype,CallType,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+AccountId%2CCreatedDate%2CTaskSubtype%2CCallType%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Apollo] No calls found. {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24242184,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT call_recording_url__c,TaskSubtype,CreatedDate,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.ERROR: [Salesforce] Request exception [400] \nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. {\"url\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000\",\"data\":{\"headers\":{\"Authorization\":\"Bearer 00D2g0000008hH4!AQEAQHWUK6nshi8dSCX9CJphxkVivcv_TK98TLOckVy4i0Z1gQfAoRRuH2LVwDXDkbTPs80wvQjczjAlOz0UEtbHoORBLi2u\"}},\"response\":{\"GuzzleHttp\\\\Psr7\\\\Stream\":\"[{\\\"message\\\":\\\"\\\\nSELECT call_recording_url__c,TaskSubtype\\\\n ^\\\\nERROR at Row:1:Column:8\\\\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\\\",\\\"errorCode\\\":\\\"INVALID_FIELD\\\"}]\"},\"fields\":[]} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.ALERT: [SyncActivity] Failed {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"\nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\",\"file\":\"/home/jiminny/app/Services/Crm/Salesforce/Client.php\",\"line\":564} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"SELECT Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type,twilio_call_sid__c,Lead_UUID__c,Opportunity__c\n FROM Task\n WHERE Type = 'Video'\n AND isClosed = true\n AND IsDeleted = false\n AND LastModifiedDate >= :from\n AND twilio_call_sid__c != NULL AND LastModifiedDate <= :to ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=SELECT+Id%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%2Ctwilio_call_sid__c%2CLead_UUID__c%2COpportunity__c%0A++++++++++++++FROM+Task%0A++++++++++++WHERE+Type+%3D+%27Video%27%0A++++++++++++++AND+isClosed+%3D+true%0A++++++++++++++AND+IsDeleted+%3D+false%0A++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A++++++++++++++AND+twilio_call_sid__c+%21%3D+NULL+AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z+ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [Twilio Video] No calls found. {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24634032,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Start {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [HubSpot] Search calls for period {\"from\":\"2026-05-28 08:14:00\",\"to\":\"2026-05-28 08:30:00\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2,\"memory_usage\":24947696,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] starting. {\"playlists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] finished. {\"normalizedPlaylists\":[],\"deletedPlaylists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring start {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring end {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:23] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"usage\":22563136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":148,\"team_id\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Syncing opportunities using strategy: lastModified {\"team\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [Hubspot] Pagination completed {\"team_id\":2,\"endpoint\":\"https://api.hubapi.com/crm/v3/objects/deals/search\",\"total_requests\":1,\"total_records_fetched\":0,\"total_elapsed_seconds\":0.4,\"average_seconds_per_request\":0.4} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Synced opportunities {\"team\":2,\"strategies\":\"lastModified\",\"sync_count\":0,\"total\":0,\"last_synced_id\":null,\"duration_ms\":432.6} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"provider\":\"hubspot\",\"status\":\"completed\",\"duration_ms\":543.02,\"usage\":22983640,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"usage\":22961848,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"2ac0447f-3c8c-4ce0-baeb-b63ddb76fa9b\",\"account\":null} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":130,\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":23.85,\"usage\":23024000,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"usage\":22984760,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"33e34a7a-1c02-4f04-87ac-22c3a385e6e3\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":306,\"sociable_id\":109,\"provider_user_id\":\"11348452\",\"expires\":1701077403,\"refresh_token_expires\":null,\"provider\":\"hubspot\",\"state\":\"full-refresh\",\"auth_scope\":null,\"retry_after\":null,\"created_at\":\"2020-09-01 16:59:04\",\"updated_at\":\"2023-11-27 09:30:03\"}}} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":109,\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":14.98,\"usage\":23047624,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Your HubSpot account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Service ending {\"runtime_seconds\":56,\"total_cycles\":5,\"files_downloaded\":0,\"empty_files\":0,\"other_portal_skipped\":0,\"total_events\":0,\"events_per_file\":0,\"avg_api_ms\":192.1,\"avg_download_ms\":0.0,\"avg_transform_ms\":0.0,\"avg_process_ms\":0.0,\"peak_memory_mb\":99.88} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Released polling lock {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"usage\":23005136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"71e3aac5-fb66-47c5-a236-2d051ae3e319\",\"account\":null} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":256,\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":34.51,\"usage\":23021248,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring start {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring end {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] STARTING batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] FINISHED batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:25] local.INFO: [Jiminny\\Jobs\\Mailbox\\CreateBatches] processed 1 inboxes and created 0 batches {\"userId\":null,\"batchSize\":30,\"maxBatches\":1000} {\"correlation_id\":\"e60597ef-aca8-4bda-bb90-18f01e96874d\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}","depth":4,"bounds":{"left":0.4331782,"top":0.09736632,"width":0.5668218,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring start {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring end {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1393,\"provider\":\"google\",\"refreshToken\":\"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1387,\"provider\":\"google\",\"refreshToken\":\"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1348,\"provider\":\"google\",\"refreshToken\":\"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1361,\"provider\":\"google\",\"refreshToken\":\"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1310,\"provider\":\"google\",\"refreshToken\":\"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1333,\"provider\":\"google\",\"refreshToken\":\"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1368,\"provider\":\"google\",\"refreshToken\":\"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1365,\"provider\":\"google\",\"refreshToken\":\"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1364,\"provider\":\"google\",\"refreshToken\":\"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1370,\"provider\":\"office\",\"refreshToken\":\"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:18Z\\\",\\\"trace_id\\\":\\\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\\\",\\\"correlation_id\\\":\\\"70bc0a6f-1565-4e74-94dc-419d94108fa9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1202,\"provider\":\"office\",\"refreshToken\":\"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:19Z\\\",\\\"trace_id\\\":\\\"d3d14dfc-1b70-40c4-b9db-fab12f748300\\\",\\\"correlation_id\\\":\\\"4c5f746c-8366-44c1-8733-6877607826db\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {\"calendar_id\":501} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1300,\"provider\":\"google\",\"refreshToken\":\"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1409,\"provider\":\"google\",\"refreshToken\":\"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1352,\"provider\":\"google\",\"refreshToken\":\"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1296,\"provider\":\"office\",\"refreshToken\":\"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"from\":null,\"to\":null,\"delta\":\"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=\",\"last_sync\":\"2024-12-09 07:12:53\",\"dateMode\":\"daily\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"integration-app\",\"crm_owner\":1695,\"team_id\":3143} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:20Z\\\",\\\"trace_id\\\":\\\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\\\",\\\"correlation_id\\\":\\\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":391,\"provider\":\"office\",\"refreshToken\":\"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"587224ad-f597-4371-b2ba-00fcd2da1b00\\\",\\\"correlation_id\\\":\\\"4e752610-95b1-4606-847f-68e00f90be0a\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1271,\"provider\":\"office\",\"refreshToken\":\"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd8bf2a7-bc49-43d7-a487-892c51e27600 Correlation ID: 51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"dd8bf2a7-bc49-43d7-a487-892c51e27600\\\",\\\"correlation_id\\\":\\\"51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1351,\"provider\":\"google\",\"refreshToken\":\"4271d15b9e60a606439caddc68337f783e472c85b03dacff14d1b6dfded9051c\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1366,\"provider\":\"google\",\"refreshToken\":\"ae21385059b2eebfd43f68aecd56eccd702a1aabb6598f1f7ab594ed8af491b4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":378} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":504} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.NOTICE: Calendar sync end {\"retrieved_calendars\":31,\"processed_calendars\":3} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [Calendar] Processing sync {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"from\":null,\"to\":null,\"delta\":\"CJ_x49O3jpIDEJ_x49O3jpIDGAUgw67KlwMow67KlwM=\",\"last_sync\":\"2026-01-19 07:48:40\",\"dateMode\":\"daily\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Pipedrive] Account not connected for user {\"userId\":\"e6538737-e7b4-455f-a37a-3e79b665a220\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":1116,\"sociable_id\":241,\"provider_user_id\":\"19555731\",\"expires\":1779091997,\"refresh_token_expires\":null,\"provider\":\"pipedrive\",\"state\":\"full-refresh\",\"auth_scope\":\"base,deals:full,activities:full,contacts:full,search:read\",\"retry_after\":null,\"created_at\":\"2023-09-08 09:44:29\",\"updated_at\":\"2026-05-18 08:13:32\"}}} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"pipedrive\",\"crm_owner\":241,\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Calendar] CRM disconnected for user so events will not be matched {\"provider\":\"pipedrive\",\"user_id\":241,\"message\":\"Your Pipedrive account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Calendar] Processing sync {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\",\"from\":null,\"to\":null,\"delta\":\"R0usmcdvmMuZCBYV0hguCBhf4uKqyU9_gdNd-le_nqqau95XAUmZwlIAy2uwtCf5sA67w6NIiDvawUSmVjpTzZO-RsxLdeS-g8Kxy6ODZQxAxafq8AJNx0hJV7T291NUvfaPYqLMv-3je3IdhAPUtXQXkHtYaBAlX_DDBxwc3zYoVVQ8iM9mQkBykdA3sh-KVYPyzi7nK4cZg5Jzpu9tHA.UA7urx3pJyhUhdo_16STIbSNXUrF-qeQVIis9stVUeY\",\"last_sync\":\"2026-05-28 07:44:06\",\"dateMode\":\"daily\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [MS Office Calendar] Skipping delta sync for daily mode {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:29:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring start {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring end {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring start {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring end {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Starting sync {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"expected_alias\":\"catch-all\",\"expected_host\":\"txt.staging.jiminny.com\"} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Sync completed {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"messages_processed\":0,\"message_ids\":[]} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Running pre-meeting notification command {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Running conference:monitor:start command for activities in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: [conference:monitor:start] No activities found in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesEnded {\"from\":\"08:25\",\"to\":\"08:30\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesWithUnfinishedSession {\"from\":\"22:20\",\"to\":\"22:25\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:23] local.NOTICE: Repairing HubSpot tokens start {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: Trying to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":59,\"provider\":\"hubspot\",\"refreshToken\":\"97b78f6e2cc49965c00c2492b602b02708b1392551e6b3f113fbaa48992af90b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.ERROR: Failed to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: Trying to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":306,\"provider\":\"hubspot\",\"refreshToken\":\"6fa6aa8cc641d131231acc3470f5c03cb3b07b2e580fb18f8acb3b1dbb72549b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: Trying to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1372,\"provider\":\"hubspot\",\"refreshToken\":\"9aa73948c761da29dce46c177cf9aee1fde483a44169ca38723f9f0597d7a8c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.NOTICE: Repairing HubSpot tokens end {\"total\":3,\"fixed\":0,\"failed\":3} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Command] Starting polling service {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Service starting {\"memory_limit\":\"256M\",\"max_execution_time\":\"0\",\"initial_memory_mb\":62.0} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Acquired polling lock {\"expires_at\":\"2026-05-28T08:32:33.444809Z\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814238,\"provider\":\"twilio-flex\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814239,\"provider\":\"xant\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814240,\"provider\":\"apollo\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814241,\"provider\":\"groove\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814242,\"provider\":\"twilio-video\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814243,\"provider\":\"hubspot\",\"team\":\"hubspot\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.WARNING: [Salesforce] Account not connected for user {\"userId\":\"cdf8b554-d951-4758-bc2b-c1b85d1cd0b9\",\"account\":null} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"salesforce\",\"crm_owner\":3,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] TeamMember found with active crm connection {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SyncActivity] Start {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.NOTICE: [TwilioFlex] Calls import start {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.ALERT: [SyncActivity] Failed {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"[HTTP 401] Unable to fetch page: Authenticate\",\"file\":\"/home/jiminny/vendor/twilio/sdk/src/Twilio/Page.php\",\"line\":60} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SyncActivity] Start {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT Playbooks_Call_Date__c,Playbooks_Call_Recording__c,CreatedDate,TaskSubtype,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+Playbooks_Call_Date__c%2CPlaybooks_Call_Recording__c%2CCreatedDate%2CTaskSubtype%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [Xant (InsideSales)] No calls found. {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24080216,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT AccountId,CreatedDate,TaskSubtype,CallType,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+AccountId%2CCreatedDate%2CTaskSubtype%2CCallType%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Apollo] No calls found. {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24242184,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT call_recording_url__c,TaskSubtype,CreatedDate,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.ERROR: [Salesforce] Request exception [400] \nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. {\"url\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000\",\"data\":{\"headers\":{\"Authorization\":\"Bearer 00D2g0000008hH4!AQEAQHWUK6nshi8dSCX9CJphxkVivcv_TK98TLOckVy4i0Z1gQfAoRRuH2LVwDXDkbTPs80wvQjczjAlOz0UEtbHoORBLi2u\"}},\"response\":{\"GuzzleHttp\\\\Psr7\\\\Stream\":\"[{\\\"message\\\":\\\"\\\\nSELECT call_recording_url__c,TaskSubtype\\\\n ^\\\\nERROR at Row:1:Column:8\\\\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\\\",\\\"errorCode\\\":\\\"INVALID_FIELD\\\"}]\"},\"fields\":[]} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.ALERT: [SyncActivity] Failed {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"\nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\",\"file\":\"/home/jiminny/app/Services/Crm/Salesforce/Client.php\",\"line\":564} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"SELECT Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type,twilio_call_sid__c,Lead_UUID__c,Opportunity__c\n FROM Task\n WHERE Type = 'Video'\n AND isClosed = true\n AND IsDeleted = false\n AND LastModifiedDate >= :from\n AND twilio_call_sid__c != NULL AND LastModifiedDate <= :to ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=SELECT+Id%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%2Ctwilio_call_sid__c%2CLead_UUID__c%2COpportunity__c%0A++++++++++++++FROM+Task%0A++++++++++++WHERE+Type+%3D+%27Video%27%0A++++++++++++++AND+isClosed+%3D+true%0A++++++++++++++AND+IsDeleted+%3D+false%0A++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A++++++++++++++AND+twilio_call_sid__c+%21%3D+NULL+AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z+ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [Twilio Video] No calls found. {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24634032,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Start {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [HubSpot] Search calls for period {\"from\":\"2026-05-28 08:14:00\",\"to\":\"2026-05-28 08:30:00\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2,\"memory_usage\":24947696,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] starting. {\"playlists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] finished. {\"normalizedPlaylists\":[],\"deletedPlaylists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring start {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring end {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:23] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"usage\":22563136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":148,\"team_id\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Syncing opportunities using strategy: lastModified {\"team\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [Hubspot] Pagination completed {\"team_id\":2,\"endpoint\":\"https://api.hubapi.com/crm/v3/objects/deals/search\",\"total_requests\":1,\"total_records_fetched\":0,\"total_elapsed_seconds\":0.4,\"average_seconds_per_request\":0.4} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Synced opportunities {\"team\":2,\"strategies\":\"lastModified\",\"sync_count\":0,\"total\":0,\"last_synced_id\":null,\"duration_ms\":432.6} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"provider\":\"hubspot\",\"status\":\"completed\",\"duration_ms\":543.02,\"usage\":22983640,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"usage\":22961848,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"2ac0447f-3c8c-4ce0-baeb-b63ddb76fa9b\",\"account\":null} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":130,\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":23.85,\"usage\":23024000,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"usage\":22984760,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"33e34a7a-1c02-4f04-87ac-22c3a385e6e3\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":306,\"sociable_id\":109,\"provider_user_id\":\"11348452\",\"expires\":1701077403,\"refresh_token_expires\":null,\"provider\":\"hubspot\",\"state\":\"full-refresh\",\"auth_scope\":null,\"retry_after\":null,\"created_at\":\"2020-09-01 16:59:04\",\"updated_at\":\"2023-11-27 09:30:03\"}}} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":109,\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":14.98,\"usage\":23047624,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Your HubSpot account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Service ending {\"runtime_seconds\":56,\"total_cycles\":5,\"files_downloaded\":0,\"empty_files\":0,\"other_portal_skipped\":0,\"total_events\":0,\"events_per_file\":0,\"avg_api_ms\":192.1,\"avg_download_ms\":0.0,\"avg_transform_ms\":0.0,\"avg_process_ms\":0.0,\"peak_memory_mb\":99.88} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Released polling lock {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"usage\":23005136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"71e3aac5-fb66-47c5-a236-2d051ae3e319\",\"account\":null} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":256,\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":34.51,\"usage\":23021248,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring start {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring end {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] STARTING batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] FINISHED batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:25] local.INFO: [Jiminny\\Jobs\\Mailbox\\CreateBatches] processed 1 inboxes and created 0 batches {\"userId\":null,\"batchSize\":30,\"maxBatches\":1000} {\"correlation_id\":\"e60597ef-aca8-4bda-bb90-18f01e96874d\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-37482055105397747
|
3613057122943418527
|
visual_change
|
accessibility
|
NULL
|
remote: Resolving deltas: 100% (10/10), completed remote: Resolving deltas: 100% (10/10), completed with 10 local objects.
2 files committed
JY-20915 fix missing header
text/html
text/html
text/html
Edit Commit Message…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
103
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {"count":0} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring start {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring end {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {"host":"docker_lamp_1"} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {"host":"docker_lamp_1","processed":0} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"calendar:sync","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1393,"provider":"google","refreshToken":"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1387,"provider":"google","refreshToken":"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1348,"provider":"google","refreshToken":"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1361,"provider":"google","refreshToken":"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1310,"provider":"google","refreshToken":"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1333,"provider":"google","refreshToken":"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1368,"provider":"google","refreshToken":"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1365,"provider":"google","refreshToken":"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1364,"provider":"google","refreshToken":"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1370,"provider":"office","refreshToken":"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:18Z\",\"trace_id\":\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\",\"correlation_id\":\"70bc0a6f-1565-4e74-94dc-419d94108fa9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1202,"provider":"office","refreshToken":"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:19Z\",\"trace_id\":\"d3d14dfc-1b70-40c4-b9db-fab12f748300\",\"correlation_id\":\"4c5f746c-8366-44c1-8733-6877607826db\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {"calendar_id":501} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1300,"provider":"google","refreshToken":"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1409,"provider":"google","refreshToken":"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1352,"provider":"google","refreshToken":"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1296,"provider":"office","refreshToken":"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","from":null,"to":null,"delta":"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=","last_sync":"2024-12-09 07:12:53","dateMode":"daily"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {"crm_provider":"integration-app","crm_owner":1695,"team_id":3143} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:20Z\",\"trace_id\":\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\",\"correlation_id\":\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":391,"provider":"office","refreshToken":"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:21Z\",\"trace_id\":\"587224ad-f597-4371-b2ba-00fcd2da1b00\",\"correlation_id\":\"4e752610-95b1-4606-847f-68e00f90be0a\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Re...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81613
|
2833
|
22
|
2026-05-28T08:32:31.877817+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957151877_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Committing…
Project: faVsco.js, menu
JY-20915-fix- Committing…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {"count":0} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring start {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring end {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {"host":"docker_lamp_1"} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {"host":"docker_lamp_1","processed":0} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"calendar:sync","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1393,"provider":"google","refreshToken":"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1387,"provider":"google","refreshToken":"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1348,"provider":"google","refreshToken":"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1361,"provider":"google","refreshToken":"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1310,"provider":"google","refreshToken":"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1333,"provider":"google","refreshToken":"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1368,"provider":"google","refreshToken":"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1365,"provider":"google","refreshToken":"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1364,"provider":"google","refreshToken":"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1370,"provider":"office","refreshToken":"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:18Z\",\"trace_id\":\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\",\"correlation_id\":\"70bc0a6f-1565-4e74-94dc-419d94108fa9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1202,"provider":"office","refreshToken":"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:19Z\",\"trace_id\":\"d3d14dfc-1b70-40c4-b9db-fab12f748300\",\"correlation_id\":\"4c5f746c-8366-44c1-8733-6877607826db\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {"calendar_id":501} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1300,"provider":"google","refreshToken":"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1409,"provider":"google","refreshToken":"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1352,"provider":"google","refreshToken":"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1296,"provider":"office","refreshToken":"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","from":null,"to":null,"delta":"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=","last_sync":"2024-12-09 07:12:53","dateMode":"daily"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {"crm_provider":"integration-app","crm_owner":1695,"team_id":3143} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:20Z\",\"trace_id\":\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\",\"correlation_id\":\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":391,"provider":"office","refreshToken":"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:21Z\",\"trace_id\":\"587224ad-f597-4371-b2ba-00fcd2da1b00\",\"correlation_id\":\"4e752610-95b1-4606-847f-68e00f90be0a\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1271,"provider":"office","refreshToken":"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Committing…","depth":2,"bounds":{"left":0.6625665,"top":0.44134077,"width":0.06948138,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":2,"bounds":{"left":0.6625665,"top":0.47326416,"width":0.06948138,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring start {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring end {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1393,\"provider\":\"google\",\"refreshToken\":\"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1387,\"provider\":\"google\",\"refreshToken\":\"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1348,\"provider\":\"google\",\"refreshToken\":\"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1361,\"provider\":\"google\",\"refreshToken\":\"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1310,\"provider\":\"google\",\"refreshToken\":\"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1333,\"provider\":\"google\",\"refreshToken\":\"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1368,\"provider\":\"google\",\"refreshToken\":\"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1365,\"provider\":\"google\",\"refreshToken\":\"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1364,\"provider\":\"google\",\"refreshToken\":\"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1370,\"provider\":\"office\",\"refreshToken\":\"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:18Z\\\",\\\"trace_id\\\":\\\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\\\",\\\"correlation_id\\\":\\\"70bc0a6f-1565-4e74-94dc-419d94108fa9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1202,\"provider\":\"office\",\"refreshToken\":\"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:19Z\\\",\\\"trace_id\\\":\\\"d3d14dfc-1b70-40c4-b9db-fab12f748300\\\",\\\"correlation_id\\\":\\\"4c5f746c-8366-44c1-8733-6877607826db\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {\"calendar_id\":501} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1300,\"provider\":\"google\",\"refreshToken\":\"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1409,\"provider\":\"google\",\"refreshToken\":\"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1352,\"provider\":\"google\",\"refreshToken\":\"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1296,\"provider\":\"office\",\"refreshToken\":\"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"from\":null,\"to\":null,\"delta\":\"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=\",\"last_sync\":\"2024-12-09 07:12:53\",\"dateMode\":\"daily\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"integration-app\",\"crm_owner\":1695,\"team_id\":3143} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:20Z\\\",\\\"trace_id\\\":\\\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\\\",\\\"correlation_id\\\":\\\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":391,\"provider\":\"office\",\"refreshToken\":\"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"587224ad-f597-4371-b2ba-00fcd2da1b00\\\",\\\"correlation_id\\\":\\\"4e752610-95b1-4606-847f-68e00f90be0a\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1271,\"provider\":\"office\",\"refreshToken\":\"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd8bf2a7-bc49-43d7-a487-892c51e27600 Correlation ID: 51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"dd8bf2a7-bc49-43d7-a487-892c51e27600\\\",\\\"correlation_id\\\":\\\"51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1351,\"provider\":\"google\",\"refreshToken\":\"4271d15b9e60a606439caddc68337f783e472c85b03dacff14d1b6dfded9051c\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1366,\"provider\":\"google\",\"refreshToken\":\"ae21385059b2eebfd43f68aecd56eccd702a1aabb6598f1f7ab594ed8af491b4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":378} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":504} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.NOTICE: Calendar sync end {\"retrieved_calendars\":31,\"processed_calendars\":3} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [Calendar] Processing sync {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"from\":null,\"to\":null,\"delta\":\"CJ_x49O3jpIDEJ_x49O3jpIDGAUgw67KlwMow67KlwM=\",\"last_sync\":\"2026-01-19 07:48:40\",\"dateMode\":\"daily\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Pipedrive] Account not connected for user {\"userId\":\"e6538737-e7b4-455f-a37a-3e79b665a220\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":1116,\"sociable_id\":241,\"provider_user_id\":\"19555731\",\"expires\":1779091997,\"refresh_token_expires\":null,\"provider\":\"pipedrive\",\"state\":\"full-refresh\",\"auth_scope\":\"base,deals:full,activities:full,contacts:full,search:read\",\"retry_after\":null,\"created_at\":\"2023-09-08 09:44:29\",\"updated_at\":\"2026-05-18 08:13:32\"}}} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"pipedrive\",\"crm_owner\":241,\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Calendar] CRM disconnected for user so events will not be matched {\"provider\":\"pipedrive\",\"user_id\":241,\"message\":\"Your Pipedrive account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Calendar] Processing sync {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\",\"from\":null,\"to\":null,\"delta\":\"R0usmcdvmMuZCBYV0hguCBhf4uKqyU9_gdNd-le_nqqau95XAUmZwlIAy2uwtCf5sA67w6NIiDvawUSmVjpTzZO-RsxLdeS-g8Kxy6ODZQxAxafq8AJNx0hJV7T291NUvfaPYqLMv-3je3IdhAPUtXQXkHtYaBAlX_DDBxwc3zYoVVQ8iM9mQkBykdA3sh-KVYPyzi7nK4cZg5Jzpu9tHA.UA7urx3pJyhUhdo_16STIbSNXUrF-qeQVIis9stVUeY\",\"last_sync\":\"2026-05-28 07:44:06\",\"dateMode\":\"daily\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [MS Office Calendar] Skipping delta sync for daily mode {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:29:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring start {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring end {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring start {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring end {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Starting sync {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"expected_alias\":\"catch-all\",\"expected_host\":\"txt.staging.jiminny.com\"} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Sync completed {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"messages_processed\":0,\"message_ids\":[]} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Running pre-meeting notification command {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Running conference:monitor:start command for activities in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: [conference:monitor:start] No activities found in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesEnded {\"from\":\"08:25\",\"to\":\"08:30\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesWithUnfinishedSession {\"from\":\"22:20\",\"to\":\"22:25\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:23] local.NOTICE: Repairing HubSpot tokens start {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: Trying to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":59,\"provider\":\"hubspot\",\"refreshToken\":\"97b78f6e2cc49965c00c2492b602b02708b1392551e6b3f113fbaa48992af90b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.ERROR: Failed to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: Trying to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":306,\"provider\":\"hubspot\",\"refreshToken\":\"6fa6aa8cc641d131231acc3470f5c03cb3b07b2e580fb18f8acb3b1dbb72549b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: Trying to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1372,\"provider\":\"hubspot\",\"refreshToken\":\"9aa73948c761da29dce46c177cf9aee1fde483a44169ca38723f9f0597d7a8c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.NOTICE: Repairing HubSpot tokens end {\"total\":3,\"fixed\":0,\"failed\":3} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Command] Starting polling service {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Service starting {\"memory_limit\":\"256M\",\"max_execution_time\":\"0\",\"initial_memory_mb\":62.0} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Acquired polling lock {\"expires_at\":\"2026-05-28T08:32:33.444809Z\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814238,\"provider\":\"twilio-flex\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814239,\"provider\":\"xant\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814240,\"provider\":\"apollo\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814241,\"provider\":\"groove\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814242,\"provider\":\"twilio-video\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814243,\"provider\":\"hubspot\",\"team\":\"hubspot\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.WARNING: [Salesforce] Account not connected for user {\"userId\":\"cdf8b554-d951-4758-bc2b-c1b85d1cd0b9\",\"account\":null} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"salesforce\",\"crm_owner\":3,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] TeamMember found with active crm connection {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SyncActivity] Start {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.NOTICE: [TwilioFlex] Calls import start {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.ALERT: [SyncActivity] Failed {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"[HTTP 401] Unable to fetch page: Authenticate\",\"file\":\"/home/jiminny/vendor/twilio/sdk/src/Twilio/Page.php\",\"line\":60} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SyncActivity] Start {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT Playbooks_Call_Date__c,Playbooks_Call_Recording__c,CreatedDate,TaskSubtype,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+Playbooks_Call_Date__c%2CPlaybooks_Call_Recording__c%2CCreatedDate%2CTaskSubtype%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [Xant (InsideSales)] No calls found. {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24080216,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT AccountId,CreatedDate,TaskSubtype,CallType,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+AccountId%2CCreatedDate%2CTaskSubtype%2CCallType%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Apollo] No calls found. {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24242184,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT call_recording_url__c,TaskSubtype,CreatedDate,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.ERROR: [Salesforce] Request exception [400] \nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. {\"url\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000\",\"data\":{\"headers\":{\"Authorization\":\"Bearer 00D2g0000008hH4!AQEAQHWUK6nshi8dSCX9CJphxkVivcv_TK98TLOckVy4i0Z1gQfAoRRuH2LVwDXDkbTPs80wvQjczjAlOz0UEtbHoORBLi2u\"}},\"response\":{\"GuzzleHttp\\\\Psr7\\\\Stream\":\"[{\\\"message\\\":\\\"\\\\nSELECT call_recording_url__c,TaskSubtype\\\\n ^\\\\nERROR at Row:1:Column:8\\\\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\\\",\\\"errorCode\\\":\\\"INVALID_FIELD\\\"}]\"},\"fields\":[]} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.ALERT: [SyncActivity] Failed {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"\nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\",\"file\":\"/home/jiminny/app/Services/Crm/Salesforce/Client.php\",\"line\":564} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"SELECT Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type,twilio_call_sid__c,Lead_UUID__c,Opportunity__c\n FROM Task\n WHERE Type = 'Video'\n AND isClosed = true\n AND IsDeleted = false\n AND LastModifiedDate >= :from\n AND twilio_call_sid__c != NULL AND LastModifiedDate <= :to ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=SELECT+Id%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%2Ctwilio_call_sid__c%2CLead_UUID__c%2COpportunity__c%0A++++++++++++++FROM+Task%0A++++++++++++WHERE+Type+%3D+%27Video%27%0A++++++++++++++AND+isClosed+%3D+true%0A++++++++++++++AND+IsDeleted+%3D+false%0A++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A++++++++++++++AND+twilio_call_sid__c+%21%3D+NULL+AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z+ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [Twilio Video] No calls found. {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24634032,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Start {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [HubSpot] Search calls for period {\"from\":\"2026-05-28 08:14:00\",\"to\":\"2026-05-28 08:30:00\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2,\"memory_usage\":24947696,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] starting. {\"playlists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] finished. {\"normalizedPlaylists\":[],\"deletedPlaylists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring start {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring end {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:23] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"usage\":22563136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":148,\"team_id\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Syncing opportunities using strategy: lastModified {\"team\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [Hubspot] Pagination completed {\"team_id\":2,\"endpoint\":\"https://api.hubapi.com/crm/v3/objects/deals/search\",\"total_requests\":1,\"total_records_fetched\":0,\"total_elapsed_seconds\":0.4,\"average_seconds_per_request\":0.4} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Synced opportunities {\"team\":2,\"strategies\":\"lastModified\",\"sync_count\":0,\"total\":0,\"last_synced_id\":null,\"duration_ms\":432.6} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"provider\":\"hubspot\",\"status\":\"completed\",\"duration_ms\":543.02,\"usage\":22983640,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"usage\":22961848,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"2ac0447f-3c8c-4ce0-baeb-b63ddb76fa9b\",\"account\":null} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":130,\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":23.85,\"usage\":23024000,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"usage\":22984760,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"33e34a7a-1c02-4f04-87ac-22c3a385e6e3\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":306,\"sociable_id\":109,\"provider_user_id\":\"11348452\",\"expires\":1701077403,\"refresh_token_expires\":null,\"provider\":\"hubspot\",\"state\":\"full-refresh\",\"auth_scope\":null,\"retry_after\":null,\"created_at\":\"2020-09-01 16:59:04\",\"updated_at\":\"2023-11-27 09:30:03\"}}} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":109,\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":14.98,\"usage\":23047624,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Your HubSpot account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Service ending {\"runtime_seconds\":56,\"total_cycles\":5,\"files_downloaded\":0,\"empty_files\":0,\"other_portal_skipped\":0,\"total_events\":0,\"events_per_file\":0,\"avg_api_ms\":192.1,\"avg_download_ms\":0.0,\"avg_transform_ms\":0.0,\"avg_process_ms\":0.0,\"peak_memory_mb\":99.88} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Released polling lock {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"usage\":23005136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"71e3aac5-fb66-47c5-a236-2d051ae3e319\",\"account\":null} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":256,\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":34.51,\"usage\":23021248,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring start {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring end {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] STARTING batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] FINISHED batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:25] local.INFO: [Jiminny\\Jobs\\Mailbox\\CreateBatches] processed 1 inboxes and created 0 batches {\"userId\":null,\"batchSize\":30,\"maxBatches\":1000} {\"correlation_id\":\"e60597ef-aca8-4bda-bb90-18f01e96874d\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}","depth":4,"bounds":{"left":0.4331782,"top":0.09736632,"width":0.5668218,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"73199e23-a066-42ba-b189-2802e0869a44\",\"trace_id\":\"e53672c2-0f50-409d-af25-84ab485c505d\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"741b2c4e-6a44-4c46-b9fb-fce017aef225\",\"trace_id\":\"804dc547-eb25-4b32-8d0f-c87019773085\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring start {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:09] local.NOTICE: Monitoring end {\"correlation_id\":\"8ae5c131-edd9-463d-8161-875f4d34320f\",\"trace_id\":\"1b6420c8-ef4e-4566-81b2-688696064648\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6f5390d3-abe7-4e56-a662-aeed1098941b\",\"trace_id\":\"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"ba694158-ea28-4ac1-b134-83ac485146e0\",\"trace_id\":\"83a26b74-baa5-407e-9fc2-2b49d65b1c77\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b79833c7-3eab-4eb7-98bb-42359039b8fb\",\"trace_id\":\"a8e159bc-867d-40af-bf7d-1228cf6d4f16\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"d51071d5-ead0-45f0-a07e-e3234074f884\",\"trace_id\":\"77173d9f-596f-405f-ae55-ba117b66455d\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1393,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1393,\"provider\":\"google\",\"refreshToken\":\"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1393,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1387,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1387,\"provider\":\"google\",\"refreshToken\":\"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1387,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1348,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1348,\"provider\":\"google\",\"refreshToken\":\"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1348,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1361,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1361,\"provider\":\"google\",\"refreshToken\":\"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1361,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1310,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1310,\"provider\":\"google\",\"refreshToken\":\"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1310,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1333,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1333,\"provider\":\"google\",\"refreshToken\":\"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1333,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1368,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1368,\"provider\":\"google\",\"refreshToken\":\"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1368,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1365,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1365,\"provider\":\"google\",\"refreshToken\":\"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1365,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1364,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1364,\"provider\":\"google\",\"refreshToken\":\"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"responseBody\":{\"error\":\"unauthorized_client\",\"error_description\":\"Unauthorized\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1364,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1370,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1370,\"provider\":\"office\",\"refreshToken\":\"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:18Z\\\",\\\"trace_id\\\":\\\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\\\",\\\"correlation_id\\\":\\\"70bc0a6f-1565-4e74-94dc-419d94108fa9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1370,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1202,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1202,\"provider\":\"office\",\"refreshToken\":\"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:19Z\\\",\\\"trace_id\\\":\\\"d3d14dfc-1b70-40c4-b9db-fab12f748300\\\",\\\"correlation_id\\\":\\\"4c5f746c-8366-44c1-8733-6877607826db\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1202,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {\"calendar_id\":501} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1300,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1300,\"provider\":\"google\",\"refreshToken\":\"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Account has been deleted\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1300,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1409,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1409,\"provider\":\"google\",\"refreshToken\":\"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1409,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1352,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1352,\"provider\":\"google\",\"refreshToken\":\"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1352,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1296,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1296,\"provider\":\"office\",\"refreshToken\":\"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"from\":null,\"to\":null,\"delta\":\"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=\",\"last_sync\":\"2024-12-09 07:12:53\",\"dateMode\":\"daily\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"integration-app\",\"crm_owner\":1695,\"team_id\":3143} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1502,\"provider\":\"google\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:20Z\\\",\\\"trace_id\\\":\\\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\\\",\\\"correlation_id\\\":\\\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1296,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":391,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":391,\"provider\":\"office\",\"refreshToken\":\"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"a33076c1-8d97-431a-99f0-85c9524e118b\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"45e201e4-60d2-407c-ae71-13e4739c0875\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"587224ad-f597-4371-b2ba-00fcd2da1b00\\\",\\\"correlation_id\\\":\\\"4e752610-95b1-4606-847f-68e00f90be0a\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":391,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1271,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1271,\"provider\":\"office\",\"refreshToken\":\"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"responseBody\":\"{\\\"error\\\":\\\"invalid_client\\\",\\\"error_description\\\":\\\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd8bf2a7-bc49-43d7-a487-892c51e27600 Correlation ID: 51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf Timestamp: 2026-05-28 08:28:21Z\\\",\\\"error_codes\\\":[7000215],\\\"timestamp\\\":\\\"2026-05-28 08:28:21Z\\\",\\\"trace_id\\\":\\\"dd8bf2a7-bc49-43d7-a487-892c51e27600\\\",\\\"correlation_id\\\":\\\"51e3eb6c-c47e-4dd7-91aa-e734fe5b65cf\\\",\\\"error_uri\\\":\\\"https://login.microsoftonline.com/error?code=7000215\\\"}\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1271,\"provider\":\"office\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1351,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1351,\"provider\":\"google\",\"refreshToken\":\"4271d15b9e60a606439caddc68337f783e472c85b03dacff14d1b6dfded9051c\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1351,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {\"socialAccountId\":1366,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1366,\"provider\":\"google\",\"refreshToken\":\"ae21385059b2eebfd43f68aecd56eccd702a1aabb6598f1f7ab594ed8af491b4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"responseBody\":{\"error\":\"invalid_grant\",\"error_description\":\"Bad Request\"}} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {\"socialAccountId\":1366,\"provider\":\"google\",\"reason\":\"Flow refresh required.\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":378} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Calendar sync job dispatched {\"calendar_id\":504} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.NOTICE: Calendar sync end {\"retrieved_calendars\":31,\"processed_calendars\":3} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"calendar:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"498bfcf1-b82c-466d-8f91-2f3f1cdf980f\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [Calendar] Processing sync {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"from\":null,\"to\":null,\"delta\":\"CJ_x49O3jpIDEJ_x49O3jpIDGAUgw67KlwMow67KlwM=\",\"last_sync\":\"2026-01-19 07:48:40\",\"dateMode\":\"daily\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Pipedrive] Account not connected for user {\"userId\":\"e6538737-e7b4-455f-a37a-3e79b665a220\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":1116,\"sociable_id\":241,\"provider_user_id\":\"19555731\",\"expires\":1779091997,\"refresh_token_expires\":null,\"provider\":\"pipedrive\",\"state\":\"full-refresh\",\"auth_scope\":\"base,deals:full,activities:full,contacts:full,search:read\",\"retry_after\":null,\"created_at\":\"2023-09-08 09:44:29\",\"updated_at\":\"2026-05-18 08:13:32\"}}} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"pipedrive\",\"crm_owner\":241,\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"pipedrive\",\"team_id\":19} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.WARNING: [Calendar] CRM disconnected for user so events will not be matched {\"provider\":\"pipedrive\",\"user_id\":241,\"message\":\"Your Pipedrive account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1115,\"provider\":\"google\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:22] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Google Calendar] Failed to watch channel for calendar {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.WARNING: [Calendar] Sync failed {\"calendarId\":\"2676cb6d-f86c-427e-bf78-591e388e3c1e\",\"code\":400,\"reason\":\"{\n \\\"error\\\": {\n \\\"errors\\\": [\n {\n \\\"domain\\\": \\\"global\\\",\n \\\"reason\\\": \\\"push.webhookUrlNotHttps\\\",\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n ],\n \\\"code\\\": 400,\n \\\"message\\\": \\\"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\\\"\n }\n}\"} {\"correlation_id\":\"9436b0cd-f0cc-4ee2-805e-472888fd5928\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1421,\"provider\":\"office\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [Calendar] Processing sync {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\",\"from\":null,\"to\":null,\"delta\":\"R0usmcdvmMuZCBYV0hguCBhf4uKqyU9_gdNd-le_nqqau95XAUmZwlIAy2uwtCf5sA67w6NIiDvawUSmVjpTzZO-RsxLdeS-g8Kxy6ODZQxAxafq8AJNx0hJV7T291NUvfaPYqLMv-3je3IdhAPUtXQXkHtYaBAlX_DDBxwc3zYoVVQ8iM9mQkBykdA3sh-KVYPyzi7nK4cZg5Jzpu9tHA.UA7urx3pJyhUhdo_16STIbSNXUrF-qeQVIis9stVUeY\",\"last_sync\":\"2026-05-28 07:44:06\",\"dateMode\":\"daily\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:28:23] local.INFO: [MS Office Calendar] Skipping delta sync for daily mode {\"calendarId\":\"9e8b1a2c-1a8f-42bd-b161-810fc0baf540\"} {\"correlation_id\":\"82ba6688-7d5c-4789-9154-9918f63e2bfd\",\"trace_id\":\"19e20da3-a204-446a-a01e-568f25ddd9fd\"}\n[2026-05-28 08:29:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"86a65904-a9f8-43c9-b0c3-1e9c8b4b9541\",\"trace_id\":\"800b02ff-3553-46a3-a8c6-c12324a1ce53\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"e5162656-5b49-4857-9917-f0cf3ddffe27\",\"trace_id\":\"a3a53cc5-596d-474c-b9c4-f6c5f7ebdfd0\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring start {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:09] local.NOTICE: Monitoring end {\"correlation_id\":\"f559463e-0c12-46df-8b53-0c50cf4aa3eb\",\"trace_id\":\"5a09aee9-5f75-4bfa-93e4-df0ff76f2326\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"9b1cc2f1-0c8a-4aa0-a9e8-57ac879839e4\",\"trace_id\":\"d69dd133-b5f0-4568-81ef-9cce3d1c5c9e\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:29:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"87e10603-9e6f-4d71-97ab-5ba67103e5fd\",\"trace_id\":\"0aae0afb-779f-4999-892d-0188e14b3dcb\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:04] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"200b132b-d8db-4010-b968-fe5e3fcc42f1\",\"trace_id\":\"7457715a-3b9d-4c35-a499-455c83e925ab\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:05] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a94ef973-dee7-4bdf-99aa-9ff06f5a5561\",\"trace_id\":\"4e37013f-2993-4c71-87d9-560f8f429d27\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring start {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:07] local.NOTICE: Monitoring end {\"correlation_id\":\"691e7103-784d-4b4a-8036-f3c624a186db\",\"trace_id\":\"991dd947-ed80-4080-8769-8ee7efc4e6a4\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"00cf8914-d440-4826-a079-ee4586e76c62\",\"trace_id\":\"d77009ee-8d7b-44ae-bb21-2080b6d48c6c\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:10] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"7c9550d0-42ed-4b1d-b5b3-7dca67f743ec\",\"trace_id\":\"84177853-9530-4b1e-bde6-3dc0c71883ee\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:28:00, 2026-05-28 08:30:00] {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"85cc6c92-262b-45c5-bbcc-4a084137fde3\",\"trace_id\":\"058bc9a3-67af-49b6-a87c-8a0a0bc0c47a\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:14] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:purge-stale\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5083d024-d669-4c6a-bde3-ce084d6a628c\",\"trace_id\":\"83110e1f-4309-4f4a-b8bb-eab5c0ec081e\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Starting sync {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"expected_alias\":\"catch-all\",\"expected_host\":\"txt.staging.jiminny.com\"} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: [TextRelayService] Sync completed {\"mailbox\":\"catch-all@txt.staging.jiminny.com\",\"messages_processed\":0,\"message_ids\":[]} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:15] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:text-relay:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc529b16-9502-4df3-b2c0-c63fcf977ed5\",\"trace_id\":\"9dd5d6d0-4cc5-454c-a0c8-0e72b69eeb29\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Running pre-meeting notification command {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:18] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-notification\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b655bca8-effa-420b-8686-95ba96f27085\",\"trace_id\":\"b1f43a19-c7ad-428e-9933-4e509b5f0055\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Running conference:monitor:start command for activities in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: [conference:monitor:start] No activities found in (2026-05-28 08:20:00, 2026-05-28 08:25:00] {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:start\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"5a8493c4-3ef7-4453-98b7-f32225d453fe\",\"trace_id\":\"056f1aea-8825-4e2c-8239-7804086e504e\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesEnded {\"from\":\"08:25\",\"to\":\"08:30\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: conference:monitor:end:Jiminny\\Console\\Commands\\Activities\\MonitorMeetingEndCommand::logActivitiesWithUnfinishedSession {\"from\":\"22:20\",\"to\":\"22:25\"} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:end\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"18a2aed9-1aae-4b10-a7fa-f75a147db499\",\"trace_id\":\"fff0c9b2-1c60-4402-b30a-2f41d9b45db3\"}\n[2026-05-28 08:30:23] local.NOTICE: Repairing HubSpot tokens start {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: Trying to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:23] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":59,\"provider\":\"hubspot\",\"refreshToken\":\"97b78f6e2cc49965c00c2492b602b02708b1392551e6b3f113fbaa48992af90b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.ERROR: Failed to refresh HubSpot token {\"account_id\":59,\"updated_at\":\"2025-10-03 09:32:05\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: Trying to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:26] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":306,\"provider\":\"hubspot\",\"refreshToken\":\"6fa6aa8cc641d131231acc3470f5c03cb3b07b2e580fb18f8acb3b1dbb72549b\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":306,\"updated_at\":\"2023-11-27 09:30:03\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: Trying to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.INFO: [SocialAccountService] Refreshing token from provider {\"socialAccountId\":1372,\"provider\":\"hubspot\",\"refreshToken\":\"9aa73948c761da29dce46c177cf9aee1fde483a44169ca38723f9f0597d7a8c4\",\"state\":\"full-refresh\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.ERROR: Failed to refresh HubSpot token {\"account_id\":1372,\"updated_at\":\"2025-10-02 14:47:06\",\"reason\":\"missing or invalid refresh token\",\"previous\":\"\"} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:27] local.NOTICE: Repairing HubSpot tokens end {\"total\":3,\"fixed\":0,\"failed\":3} {\"correlation_id\":\"338516a2-06f3-41cf-8f11-0d2c8a0b2a29\",\"trace_id\":\"58fc6994-1c77-429c-8c16-14c4bd8f57c4\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:transcription:retry-failed\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f73071c7-8696-459f-8aff-e61a7c6b30e6\",\"trace_id\":\"d72fc2ce-5064-4877-b401-10891378e1bc\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Command] Starting polling service {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Service starting {\"memory_limit\":\"256M\",\"max_execution_time\":\"0\",\"initial_memory_mb\":62.0} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Acquired polling lock {\"expires_at\":\"2026-05-28T08:32:33.444809Z\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:33] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:pre-meeting-reminder\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"720d5c87-3d13-4193-87c9-efb8dc6df7c8\",\"trace_id\":\"a9d9c9fe-db29-44a1-a5f6-1905d48dde90\"}\n[2026-05-28 08:30:33] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:35] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:reset-governor\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c692a62b-3b1a-4ff3-b965-388a7d12f619\",\"trace_id\":\"d1bdfdec-73bd-499f-a31e-b25a864da976\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:38] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814238,\"provider\":\"twilio-flex\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814239,\"provider\":\"xant\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814240,\"provider\":\"apollo\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814241,\"provider\":\"groove\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814242,\"provider\":\"twilio-video\",\"team\":\"jiminny\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Dispatching activity sync job {\"import_id\":814243,\"provider\":\"hubspot\",\"team\":\"hubspot\"} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:39] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"activity:sync\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"c6f2bef5-da3d-4403-84b7-84c355175282\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:fail-stalled\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6d797df-5275-4cf1-8ddd-300c125df8da\",\"trace_id\":\"2b46c31f-aced-4324-a70a-6395f0a72618\"}\n[2026-05-28 08:30:42] local.WARNING: [Salesforce] Account not connected for user {\"userId\":\"cdf8b554-d951-4758-bc2b-c1b85d1cd0b9\",\"account\":null} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"salesforce\",\"crm_owner\":3,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [CrmOwnerResolver] TeamMember found with active crm connection {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1194,\"provider\":\"twilio-flex\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.INFO: [SyncActivity] Start {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:42] local.NOTICE: [TwilioFlex] Calls import start {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.ALERT: [SyncActivity] Failed {\"import_id\":814238,\"provider\":\"twilio-flex\",\"provider_id\":317,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"[HTTP 401] Unable to fetch page: Authenticate\",\"file\":\"/home/jiminny/vendor/twilio/sdk/src/Twilio/Page.php\",\"line\":60} {\"correlation_id\":\"d90e1584-bf02-4654-b950-685da6f49697\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [SyncActivity] Start {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT Playbooks_Call_Date__c,Playbooks_Call_Recording__c,CreatedDate,TaskSubtype,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:43] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+Playbooks_Call_Date__c%2CPlaybooks_Call_Recording__c%2CCreatedDate%2CTaskSubtype%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:44] local.INFO: [Xant (InsideSales)] No calls found. {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814239,\"provider\":\"xant\",\"provider_id\":161,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24080216,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"664afeb1-65f0-4713-918d-c7644e36eda4\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT AccountId,CreatedDate,TaskSubtype,CallType,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+AccountId%2CCreatedDate%2CTaskSubtype%2CCallType%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Apollo] No calls found. {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] End {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Memory usage {\"import_id\":814240,\"provider\":\"apollo\",\"provider_id\":441,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24242184,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"82a57baa-c1eb-42dc-b082-fd7d3913c037\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"\n SELECT call_recording_url__c,TaskSubtype,CreatedDate,CallType,CallDurationInSeconds,Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type\n FROM Task\n WHERE IsDeleted = false\n AND LastModifiedDate >= :from\n AND LastModifiedDate <= :to\n ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:bullhorn:ping\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b2b37795-cfa8-472a-b681-322ce27c0e08\",\"trace_id\":\"605e54f2-d4f9-4683-b3fd-6c1c23e691b7\"}\n[2026-05-28 08:30:44] local.ERROR: [Salesforce] Request exception [400] \nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. {\"url\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=%0A++++++++++++SELECT+call_recording_url__c%2CTaskSubtype%2CCreatedDate%2CCallType%2CCallDurationInSeconds%2CId%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%0A++++++++++++++FROM+Task%0A+++++++++++++WHERE+IsDeleted+%3D+false%0A+++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A+++++++++++++++AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z%0A++++++++++ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000\",\"data\":{\"headers\":{\"Authorization\":\"Bearer 00D2g0000008hH4!AQEAQHWUK6nshi8dSCX9CJphxkVivcv_TK98TLOckVy4i0Z1gQfAoRRuH2LVwDXDkbTPs80wvQjczjAlOz0UEtbHoORBLi2u\"}},\"response\":{\"GuzzleHttp\\\\Psr7\\\\Stream\":\"[{\\\"message\\\":\\\"\\\\nSELECT call_recording_url__c,TaskSubtype\\\\n ^\\\\nERROR at Row:1:Column:8\\\\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\\\",\\\"errorCode\\\":\\\"INVALID_FIELD\\\"}]\"},\"fields\":[]} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.ALERT: [SyncActivity] Failed {\"import_id\":814241,\"provider\":\"groove\",\"provider_id\":228,\"team\":\"jiminny\",\"team_id\":1,\"reason\":\"\nSELECT call_recording_url__c,TaskSubtype\n ^\nERROR at Row:1:Column:8\nNo such column 'call_recording_url__c' on entity 'Task'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.\",\"file\":\"/home/jiminny/app/Services/Crm/Salesforce/Client.php\",\"line\":564} {\"correlation_id\":\"db0b2bb2-4954-4403-80fd-0f02be18b0fb\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"salesforce\",\"crm_owner\":143,\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1500,\"provider\":\"salesforce\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [SyncActivity] Start {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Performing query {\"query\":\"SELECT Id,OwnerId,WhoId,WhatId,Priority,ActivityDate,Subject,Description,Status,Type,twilio_call_sid__c,Lead_UUID__c,Opportunity__c\n FROM Task\n WHERE Type = 'Video'\n AND isClosed = true\n AND IsDeleted = false\n AND LastModifiedDate >= :from\n AND twilio_call_sid__c != NULL AND LastModifiedDate <= :to ORDER BY LastModifiedDate ASC\n LIMIT :limit\",\"params\":{\"from\":\"2026-05-28T08:14:00Z\",\"to\":\"2026-05-28T08:30:00Z\",\"ownerId\":null,\"subType\":null,\"limit\":5000}} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:44] local.INFO: [Salesforce] Sending request {\"endpoint\":\"https://jiminny--stagingenv.sandbox.my.salesforce.com/services/data/v50.0/query/?q=SELECT+Id%2COwnerId%2CWhoId%2CWhatId%2CPriority%2CActivityDate%2CSubject%2CDescription%2CStatus%2CType%2Ctwilio_call_sid__c%2CLead_UUID__c%2COpportunity__c%0A++++++++++++++FROM+Task%0A++++++++++++WHERE+Type+%3D+%27Video%27%0A++++++++++++++AND+isClosed+%3D+true%0A++++++++++++++AND+IsDeleted+%3D+false%0A++++++++++++++AND+LastModifiedDate+%3E%3D+2026-05-28T08%3A14%3A00Z%0A++++++++++++++AND+twilio_call_sid__c+%21%3D+NULL+AND+LastModifiedDate+%3C%3D+2026-05-28T08%3A30%3A00Z+ORDER+BY+LastModifiedDate+ASC%0A+++++++++++++LIMIT+5000 GET\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [Twilio Video] No calls found. {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814242,\"provider\":\"twilio-video\",\"provider_id\":243,\"team\":\"jiminny\",\"team_id\":1,\"memory_usage\":24634032,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"0b355e21-99f2-41eb-8157-fe7cd227fa58\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":89,\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":408,\"provider\":\"hubspot\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Start {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [HubSpot] Search calls for period {\"from\":\"2026-05-28 08:14:00\",\"to\":\"2026-05-28 08:30:00\"} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] End {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:45] local.INFO: [SyncActivity] Memory usage {\"import_id\":814243,\"provider\":\"hubspot\",\"provider_id\":31,\"team\":\"hubspot\",\"team_id\":2,\"memory_usage\":24947696,\"memory_real_usage\":65011712,\"pid\":21708} {\"correlation_id\":\"4d0058c7-c318-4aea-82c0-403eadc12ccc\",\"trace_id\":\"d36c89c2-6acf-4497-b03c-93e5a090ea28\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:46] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"nudges:send\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f3e257b6-82bb-440c-bf76-855ac528e4e8\",\"trace_id\":\"f8a31218-7290-45ac-8fe1-ffb1b8527521\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] starting. {\"playlists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: [Jiminny\\Component\\Playlist\\Command\\NormalizeSortCommand::handle] finished. {\"normalizedPlaylists\":[],\"deletedPlaylists\":[]} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:50] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"jiminny:playlists:normalize-sort\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"a64b1836-79a1-41da-a4b0-bc0a9703a94b\",\"trace_id\":\"c53faedc-a7a7-41b7-8e51-e84dc2755d79\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:30:59] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:07] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"41db30ba-33c5-46f1-b8bd-5d9e86a70d12\",\"trace_id\":\"a5e2028d-ca41-4ba1-9ddd-a246f83ef4cc\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:12] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"f6ed0a05-caa1-4cb6-ae83-63f44ae4e0d6\",\"trace_id\":\"16cd898d-57a1-4b74-90d1-f9223bbd8d7a\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring start {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:15] local.NOTICE: Monitoring end {\"correlation_id\":\"cdf384ea-4f59-4411-8ebf-efc299e4a1c8\",\"trace_id\":\"b069d3c8-2f77-4698-bd53-97de373652e8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:17] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"940a264b-4aee-40a0-a527-e101ea555a38\",\"trace_id\":\"cd9169ad-4c1e-452d-b7cb-66005aae4dc8\"}\n[2026-05-28 08:31:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:23] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:24] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"b798f381-71f2-4c51-a135-f91f09330cfd\",\"trace_id\":\"b44ed325-23f7-4f8b-a447-4c8d0ee99d01\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:27] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"crm:sync-hubspot-objects\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"2d631328-f2b9-44f3-83d3-613b7b9b9ddc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"usage\":22563136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Fetching token {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SocialAccountService] Token retrieved {\"socialAccountId\":1499,\"provider\":\"hubspot\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [EncryptedTokenManager] Generating access token. {\"mode\":\"legacy\"} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {\"crm_provider\":\"hubspot\",\"crm_owner\":148,\"team_id\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Syncing opportunities using strategy: lastModified {\"team\":2} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [Hubspot] Pagination completed {\"team_id\":2,\"endpoint\":\"https://api.hubapi.com/crm/v3/objects/deals/search\",\"total_requests\":1,\"total_records_fetched\":0,\"total_elapsed_seconds\":0.4,\"average_seconds_per_request\":0.4} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [HubSpot] Synced opportunities {\"team\":2,\"strategies\":\"lastModified\",\"sync_count\":0,\"total\":0,\"last_synced_id\":null,\"duration_ms\":432.6} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"abae74b8-bfa8-4383-9a7f-89f4bf2bdbb4\",\"provider\":\"hubspot\",\"status\":\"completed\",\"duration_ms\":543.02,\"usage\":22983640,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"5b5669c7-bb21-4c59-97e6-edafd6520cc4\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"usage\":22961848,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"2ac0447f-3c8c-4ce0-baeb-b63ddb76fa9b\",\"account\":null} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":130,\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":42} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2d49a54-b645-4637-a7ae-a86cfce6e8e4\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":23.85,\"usage\":23024000,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"32799697-dd65-4ad4-b1d1-cd553c4510f8\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"usage\":22984760,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"33e34a7a-1c02-4f04-87ac-22c3a385e6e3\",\"account\":{\"Jiminny\\\\Models\\\\SocialAccount\":{\"id\":306,\"sociable_id\":109,\"provider_user_id\":\"11348452\",\"expires\":1701077403,\"refresh_token_expires\":null,\"provider\":\"hubspot\",\"state\":\"full-refresh\",\"auth_scope\":null,\"retry_after\":null,\"created_at\":\"2020-09-01 16:59:04\",\"updated_at\":\"2023-11-27 09:30:03\"}}} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":109,\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":29} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:28] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"b2b115eb-93ce-4d1b-929c-173757df8fba\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":14.98,\"usage\":23047624,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Your HubSpot account has become disconnected. Please login to Jiminny to reconnect.\"} {\"correlation_id\":\"0732b08b-2bf7-4f5b-93b6-9b2889269535\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Getting offset from database {\"offset\":\"\",\"jiminny_team_id\":1} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal API] Fetching latest journal entry {\"url\":\"https://api.hubapi.com/webhooks/v4/journal/latest\"} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] No data {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot Journal Polling] Maximum empty results reached, stopping {\"empty_results\":5,\"max_empty_results\":5} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Service ending {\"runtime_seconds\":56,\"total_cycles\":5,\"files_downloaded\":0,\"empty_files\":0,\"other_portal_skipped\":0,\"total_events\":0,\"events_per_file\":0,\"avg_api_ms\":192.1,\"avg_download_ms\":0.0,\"avg_transform_ms\":0.0,\"avg_process_ms\":0.0,\"peak_memory_mb\":99.88} {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [HubSpot Journal Polling] Released polling lock {\"correlation_id\":\"69a84dc3-5ad9-4eb1-8057-5b1e80de395e\",\"trace_id\":\"5e8af621-8c17-4344-bc12-18da6b71d516\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Starting sync {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"usage\":23005136,\"real_usage\":65011712,\"pid\":21703} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.WARNING: [HubSpot] Account not connected for user {\"userId\":\"71e3aac5-fb66-47c5-a236-2d051ae3e319\",\"account\":null} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] Integration owner is not connected, attempting team members {\"crm_provider\":\"hubspot\",\"crm_owner\":256,\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team members found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [CrmOwnerResolver] No team member found with active crm connection {\"crm_provider\":\"hubspot\",\"team_id\":49} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:31:29] local.INFO: [SyncHubspotObjects] Sync finished {\"team\":\"c6b9d6b0-b48d-4832-a68c-a57d60651888\",\"provider\":\"hubspot\",\"status\":\"disconnected\",\"duration_ms\":34.51,\"usage\":23021248,\"real_usage\":65011712,\"pid\":21703,\"reason\":\"Social account for HubSpot cannot be found. Please login to Jiminny to connect.\"} {\"correlation_id\":\"4f83a1ac-418f-4f49-8377-328b614306fc\",\"trace_id\":\"aa1cae8a-acff-4b75-8a3d-e4f9ed33c815\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {\"count\":0} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:06] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"meeting-bot:schedule-bot\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"35f98b1b-7b16-4e79-a420-7e9818097d24\",\"trace_id\":\"d66deb58-fa13-486f-a866-2cac402dc589\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:09] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"dialers:monitor-activities\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"bc6784c1-c46f-4295-be09-87334f4baa39\",\"trace_id\":\"74b00236-4ed0-4464-8b07-99c328ab6461\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring start {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:11] local.NOTICE: Monitoring end {\"correlation_id\":\"caf4d1dd-2a52-40f5-834a-f9148f642e83\",\"trace_id\":\"1312bdcc-7e8b-480a-a935-2433fb79dc70\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:16] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:skip-lists:refresh\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"64d86889-1f0d-4f7d-a1ac-6f56e58e775e\",\"trace_id\":\"b184d66b-49f8-40ec-afbe-2e76e9c7d952\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] STARTING batch process {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: [EmailSchedule] FINISHED batch process {\"host\":\"docker_lamp_1\",\"processed\":0} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:20] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:process\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"8e6dd4bc-4f44-4fb2-b2ba-9e2f385996ef\",\"trace_id\":\"7767e0ca-37a3-43a5-972e-ea9a1bedea2f\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:30:00, 2026-05-28 08:32:00] {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:22] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"conference:monitor:count\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":62.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"6750ab25-6dff-4e7b-9f6e-bc7d1fc4221a\",\"trace_id\":\"3db6ce9b-167d-4214-a32c-67c611aa2bbe\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage before starting command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryPeakBeforeCommandInMb\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] STARTING batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: [EmailSchedule] FINISHED batch create {\"host\":\"docker_lamp_1\"} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:23] local.INFO: Jiminny\\Console\\Commands\\Command::run Memory usage for command {\"command\":\"mailbox:batch:create\",\"memoryBeforeCommandInMb\":60.0,\"memoryAfterCommandInMB\":60.0,\"memoryPeakBeforeCommandInMb\":99.883,\"memoryPeakAfterCommandInMB\":99.883} {\"correlation_id\":\"04510c2c-638c-4687-81d7-b12e76f41df3\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}\n[2026-05-28 08:32:25] local.INFO: [Jiminny\\Jobs\\Mailbox\\CreateBatches] processed 1 inboxes and created 0 batches {\"userId\":null,\"batchSize\":30,\"maxBatches\":1000} {\"correlation_id\":\"e60597ef-aca8-4bda-bb90-18f01e96874d\",\"trace_id\":\"87f0bb69-8fd1-47f1-9c9e-3b0ac3d6bd60\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4191285066257905338
|
3613057122943418527
|
visual_change
|
accessibility
|
NULL
|
Committing…
Project: faVsco.js, menu
JY-20915-fix- Committing…
Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: [ScheduleBotCommand] Dispatched activities to capture {"count":0} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:04] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"meeting-bot:schedule-bot","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"73199e23-a066-42ba-b189-2802e0869a44","trace_id":"e53672c2-0f50-409d-af25-84ab485c505d"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:06] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"dialers:monitor-activities","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"741b2c4e-6a44-4c46-b9fb-fce017aef225","trace_id":"804dc547-eb25-4b32-8d0f-c87019773085"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring start {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:09] local.NOTICE: Monitoring end {"correlation_id":"8ae5c131-edd9-463d-8161-875f4d34320f","trace_id":"1b6420c8-ef4e-4566-81b2-688696064648"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:10] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:skip-lists:refresh","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"6f5390d3-abe7-4e56-a662-aeed1098941b","trace_id":"b57dc2df-2f4d-4d3b-b09a-aa6e61205d5e"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] STARTING batch process {"host":"docker_lamp_1"} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: [EmailSchedule] FINISHED batch process {"host":"docker_lamp_1","processed":0} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:12] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:process","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"ba694158-ea28-4ac1-b134-83ac485146e0","trace_id":"83a26b74-baa5-407e-9fc2-2b49d65b1c77"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Running conference:monitor:count command for activities in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: [conference:monitor:count] No activities found in (2026-05-28 08:26:00, 2026-05-28 08:28:00] {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:14] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"conference:monitor:count","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"b79833c7-3eab-4eb7-98bb-42359039b8fb","trace_id":"a8e159bc-867d-40af-bf7d-1228cf6d4f16"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage before starting command {"command":"calendar:sync","memoryBeforeCommandInMb":60.0,"memoryPeakBeforeCommandInMb":99.883} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.NOTICE: Calendar sync start {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: Jiminny\Console\Commands\Command::run Memory usage for command {"command":"mailbox:batch:retry-failed","memoryBeforeCommandInMb":60.0,"memoryAfterCommandInMB":62.0,"memoryPeakBeforeCommandInMb":99.883,"memoryPeakAfterCommandInMB":99.883} {"correlation_id":"d51071d5-ead0-45f0-a07e-e3234074f884","trace_id":"77173d9f-596f-405f-ae55-ba117b66455d"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1393,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:16] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1393,"provider":"google","refreshToken":"5aa7e2d96b53201cd16fca5d2e4ef3ad03320971fc064781d18aee3ae7b99fbf","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1393,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1387,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1387,"provider":"google","refreshToken":"8157ac6de94842937194009e9c50e459253600f799dacf6a40755ffdbeb5bba6","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1387,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1348,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1348,"provider":"google","refreshToken":"9e7d13d3032d0cb1b79d8e95aef01383e8e91eb52ff8ee960c8a0b6b95cd8c73","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1348,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1361,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1361,"provider":"google","refreshToken":"6c843da199c2b9907445329304fcc4ec5057a4ee748d8299641764395c08e1fd","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1361,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1310,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1310,"provider":"google","refreshToken":"e34818922c2830a660813a63f6169a4a9a992ae2cccd7dc8dd7796cfdb470ef1","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1310,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1333,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1333,"provider":"google","refreshToken":"6c902986546d8e8da1dc539b046cdc1d458f519acc972e5b5f1d6a1a295165e0","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1333,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1368,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:17] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1368,"provider":"google","refreshToken":"d2f128898ff8543bd16b69cfae37896ab85119b0f5ed2b431d739593bb600333","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1368,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1365,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1365,"provider":"google","refreshToken":"7676e4a9afcd082b413248ab5ec6e487021fec6a9bdf315860a59cefad9caad8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1365,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1364,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1364,"provider":"google","refreshToken":"dd5882ebce76e645292ce33ae74238abbb77c0a4ecc6a2bfe723cad82e72ba8e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","responseBody":{"error":"unauthorized_client","error_description":"Unauthorized"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1364,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1370,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1370,"provider":"office","refreshToken":"b7ee8035306d0043cea6e00e7c4fe14f745e44074a1194db62a31cdf8b70af3e","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 41d8db5c-a91f-41a6-9b5c-22a6c99b9100 Correlation ID: 70bc0a6f-1565-4e74-94dc-419d94108fa9 Timestamp: 2026-05-28 08:28:18Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:18Z\",\"trace_id\":\"41d8db5c-a91f-41a6-9b5c-22a6c99b9100\",\"correlation_id\":\"70bc0a6f-1565-4e74-94dc-419d94108fa9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1370,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1202,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:18] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1202,"provider":"office","refreshToken":"b458799ccc29b21a6e2eb5260fdb63e49ccba21bf942a3973fb63799bd7f0afe","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: d3d14dfc-1b70-40c4-b9db-fab12f748300 Correlation ID: 4c5f746c-8366-44c1-8733-6877607826db Timestamp: 2026-05-28 08:28:19Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:19Z\",\"trace_id\":\"d3d14dfc-1b70-40c4-b9db-fab12f748300\",\"correlation_id\":\"4c5f746c-8366-44c1-8733-6877607826db\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1202,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: Calendar sync job dispatched {"calendar_id":501} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1300,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1300,"provider":"google","refreshToken":"4b811db0725fd9602a95943519a7da935e2a5065da7d9ebfcb170752e3e1ddb8","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Account has been deleted"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1300,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1409,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1409,"provider":"google","refreshToken":"e2a3f2d06894894eed1ee87d9db1ace77d4d42ee6e1288a8940ad2c10333b0c4","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1409,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1352,"provider":"google"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1352,"provider":"google","refreshToken":"dd4b16b00fdc1216da6b717c02338c073636e29162826b2de6db3f064fc029eb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","responseBody":{"error":"invalid_grant","error_description":"Bad Request"}} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1352,"provider":"google","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1296,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:19] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1296,"provider":"office","refreshToken":"011ae723c9d800c674e0b4be76f49fc046dac7d501b66c59ef0d9549cfa56ae5","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Calendar] Processing sync {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","from":null,"to":null,"delta":"CIiFh8TP44kDEIiFh8TP44kDGAUgkZvkzgIokZvkzgI=","last_sync":"2024-12-09 07:12:53","dateMode":"daily"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [CrmOwnerResolver] Integration owner matched as CRM Owner {"crm_provider":"integration-app","crm_owner":1695,"team_id":3143} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token retrieved {"socialAccountId":1502,"provider":"google"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: dd83a147-95bc-407c-8c9b-3c14e7cb7d00 Correlation ID: bb16bae3-b3c4-467e-bd95-4e7ab85364c9 Timestamp: 2026-05-28 08:28:20Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:20Z\",\"trace_id\":\"dd83a147-95bc-407c-8c9b-3c14e7cb7d00\",\"correlation_id\":\"bb16bae3-b3c4-467e-bd95-4e7ab85364c9\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":1296,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":391,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":391,"provider":"office","refreshToken":"00045eebae0f39b34887c6d53f92ae78064f7145e1f4b67754aebd03cfb2d881","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.INFO: [Google Calendar] Failed to watch channel for calendar {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:20] local.WARNING: [Calendar] Sync failed {"calendarId":"a33076c1-8d97-431a-99f0-85c9524e118b","code":400,"reason":"{
\"error\": {
\"errors\": [
{
\"domain\": \"global\",
\"reason\": \"push.webhookUrlNotHttps\",
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
],
\"code\": 400,
\"message\": \"WebHook callback must be HTTPS: /webhook/calendar/google?resourceType=event\"
}
}"} {"correlation_id":"45e201e4-60d2-407c-ae71-13e4739c0875","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","responseBody":"{\"error\":\"invalid_client\",\"error_description\":\"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'bbcbb2ef-6200-4fae-82bd-d81f5dd738da'. Trace ID: 587224ad-f597-4371-b2ba-00fcd2da1b00 Correlation ID: 4e752610-95b1-4606-847f-68e00f90be0a Timestamp: 2026-05-28 08:28:21Z\",\"error_codes\":[7000215],\"timestamp\":\"2026-05-28 08:28:21Z\",\"trace_id\":\"587224ad-f597-4371-b2ba-00fcd2da1b00\",\"correlation_id\":\"4e752610-95b1-4606-847f-68e00f90be0a\",\"error_uri\":\"https://login.microsoftonline.com/error?code=7000215\"}"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountObserver] Saving model {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.ERROR: [SocialAccountService] Failed to refresh token {"socialAccountId":391,"provider":"office","reason":"Flow refresh required."} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Fetching token {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Token needs refreshing {"socialAccountId":1271,"provider":"office"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [EncryptedTokenManager] Generating access token. {"mode":"legacy"} {"correlation_id":"498bfcf1-b82c-466d-8f91-2f3f1cdf980f","trace_id":"19e20da3-a204-446a-a01e-568f25ddd9fd"}
[2026-05-28 08:28:21] local.INFO: [SocialAccountService] Refreshing token from provider {"socialAccountId":1271,"provider":"office","refreshToken":"118cde2c06993147b07ccaec4cbcd5026a819dea6c71081166a492933e392afb","state":"full-refresh"} {"correlation_id":"498bfcf1-b82c-...
|
81612
|
NULL
|
NULL
|
NULL
|
|
81605
|
2832
|
18
|
2026-05-28T08:32:13.729686+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957133729_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Editor for laravel.log...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Editor for laravel.log","depth":4,"role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-3638810784233747753
|
-6006532924280239189
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Editor for laravel.log...
|
81604
|
NULL
|
NULL
|
NULL
|
|
81604
|
2832
|
17
|
2026-05-28T08:32:10.997533+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957130997_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"","depth":4,"on_screen":true,"value":"","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2129860785133473404
|
-4704983834769847381
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81603
|
2833
|
17
|
2026-05-28T08:31:47.546303+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957107546_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.40223464},"on_screen":true,"value":"","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2129860785133473404
|
-4704983834769847381
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81602
|
2832
|
16
|
2026-05-28T08:31:45.911289+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957105911_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"","depth":4,"on_screen":true,"value":"","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2628780741070192589
|
-5857843767832835157
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification...
|
81600
|
NULL
|
NULL
|
NULL
|
|
81601
|
2833
|
16
|
2026-05-28T08:31:44.488823+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957104488_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFV faVsco.|s ~ProjectvViewNeweNNC$2 JY-209 PhpStormFV faVsco.|s ~ProjectvViewNeweNNC$2 JY-20915-fix-missioCoocKetucioTOOI-Window) Kernel.php© SyneMailbox.php©InternetMessagelnterface.phg© TextRelayServiceTest.phpfyminny.oheE env.production© MailChannelService.phpclass TextReLayServiceo Textrelkysewice.onoavare tuncczon csroncurehcchvarohaehtMeetingGeneratoranoucadorEOHUNPlaybooks—KeCaLA& Dockerfie1 catch (\Exception $e) (Log: :error ((message:)" [TextRelayService) Failed to inspect message', t'nessage_id' => Snessageid,'exception' => Se-›getMessageO).Jotaeo(Sentry::captureException(Se):a Team#UserPilotWebhookC AbstractSemvice cno©ActivityProviderFactory.phpCActviysemce cno©ApiResponseService.phpeeonaraneacarhes ood©InsightSeatService.php© InstantMeetingService.php© IntercomService.php©lpapiClient.phpirávate function natchesExpectedRecipfent (string Srecipient, string SexpoctedAlias, string SexpectedHoDoants - exorodelseif (count(Sparts) la= 2 ll strcasecno(Spartsii]. SexpectedHost) (a= 0)%return false.Changes o luesF .env.local app© JiminnyDebugCommand.php app/Console/Commandsme logging.php config@ PlaybackService.pho app/Services© TextRelayService.php app/Services/Mailoex RehyswMicalieaoho› Unversioned Files 9 filesE laravellog X 4 SF jiminny@localhost)HSJocal ([iminny@localhost)A console (PROD)A console [STAGING)A console (EU]TO0У L7oo tnu comoy tiroteeU TextRelayServiceTest~+0 .fox@TextRelayServiceTest-phprner hensewietResdTextRelayScrvicalest.oho #L154-188eexKeayeMicesthontRead TextRelayServiceTest.php #L150-199Sasrched testistorcurrent Environment.allsBackio ohesder in testerUnSamrices Moiln extRelay Service est.oho.I need to check if there's a duplicate test now. Let me search for all test methods in the file:ResonexRehyscwicelcscono 00-2lD TextRelayServiceTest.phpAsk amahioo+ < Code SWE-1.6+1-10003ditterences+ → , Side-by-side viewerDo notignorey Highlight words71 • ?8828865601Sthiisoassent sailse Sresultpublic function testIsForCurrentEnvironnentIgnoresToHeader(): voidConfig::set('jininny-google_text_host', 'txt.jiminny.com');Snessage = Sthis-›createMock(GnailMessage: :class);Sresult = Snethod-›invoke(Sservice, SgnailService, 'catch-all', 'asg123', 'catch-all', 'txt.jiminny.com'):Sthis->assertFalse(Sresult);nublic functzion testlefondunnentEnwironnentWithEnotvHeadeneOe voi.nethodosserrccesgtolet ruePurtent vereionSthisosassentFalselSresultpublic function testIsForCurrentEnvironmentFallsBackToToHeader(): voidConfig::set("jininny.google text host'*txt.jininny.com');Smessage = Sthis-›createMock(GmailMessage::class):Smethod->setAccessibte(true);Sresult = Snethod->invoke(Sservice, SgnailService, 'catch-all', 'nsg123', 'catch-all', 'txt.jininny.con'):Scnis->asserclruelSresutooublie funatzion testleforCurcentEnvirdoc h0d->eeeeherueTAGEnactArem ditee sooutwnderAmereyenhensno....
|
NULL
|
6710810205627921530
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhpStormFV faVsco.|s ~ProjectvViewNeweNNC$2 JY-209 PhpStormFV faVsco.|s ~ProjectvViewNeweNNC$2 JY-20915-fix-missioCoocKetucioTOOI-Window) Kernel.php© SyneMailbox.php©InternetMessagelnterface.phg© TextRelayServiceTest.phpfyminny.oheE env.production© MailChannelService.phpclass TextReLayServiceo Textrelkysewice.onoavare tuncczon csroncurehcchvarohaehtMeetingGeneratoranoucadorEOHUNPlaybooks—KeCaLA& Dockerfie1 catch (\Exception $e) (Log: :error ((message:)" [TextRelayService) Failed to inspect message', t'nessage_id' => Snessageid,'exception' => Se-›getMessageO).Jotaeo(Sentry::captureException(Se):a Team#UserPilotWebhookC AbstractSemvice cno©ActivityProviderFactory.phpCActviysemce cno©ApiResponseService.phpeeonaraneacarhes ood©InsightSeatService.php© InstantMeetingService.php© IntercomService.php©lpapiClient.phpirávate function natchesExpectedRecipfent (string Srecipient, string SexpoctedAlias, string SexpectedHoDoants - exorodelseif (count(Sparts) la= 2 ll strcasecno(Spartsii]. SexpectedHost) (a= 0)%return false.Changes o luesF .env.local app© JiminnyDebugCommand.php app/Console/Commandsme logging.php config@ PlaybackService.pho app/Services© TextRelayService.php app/Services/Mailoex RehyswMicalieaoho› Unversioned Files 9 filesE laravellog X 4 SF jiminny@localhost)HSJocal ([iminny@localhost)A console (PROD)A console [STAGING)A console (EU]TO0У L7oo tnu comoy tiroteeU TextRelayServiceTest~+0 .fox@TextRelayServiceTest-phprner hensewietResdTextRelayScrvicalest.oho #L154-188eexKeayeMicesthontRead TextRelayServiceTest.php #L150-199Sasrched testistorcurrent Environment.allsBackio ohesder in testerUnSamrices Moiln extRelay Service est.oho.I need to check if there's a duplicate test now. Let me search for all test methods in the file:ResonexRehyscwicelcscono 00-2lD TextRelayServiceTest.phpAsk amahioo+ < Code SWE-1.6+1-10003ditterences+ → , Side-by-side viewerDo notignorey Highlight words71 • ?8828865601Sthiisoassent sailse Sresultpublic function testIsForCurrentEnvironnentIgnoresToHeader(): voidConfig::set('jininny-google_text_host', 'txt.jiminny.com');Snessage = Sthis-›createMock(GnailMessage: :class);Sresult = Snethod-›invoke(Sservice, SgnailService, 'catch-all', 'asg123', 'catch-all', 'txt.jiminny.com'):Sthis->assertFalse(Sresult);nublic functzion testlefondunnentEnwironnentWithEnotvHeadeneOe voi.nethodosserrccesgtolet ruePurtent vereionSthisosassentFalselSresultpublic function testIsForCurrentEnvironmentFallsBackToToHeader(): voidConfig::set("jininny.google text host'*txt.jininny.com');Smessage = Sthis-›createMock(GmailMessage::class):Smethod->setAccessibte(true);Sresult = Snethod->invoke(Sservice, SgnailService, 'catch-all', 'nsg123', 'catch-all', 'txt.jininny.con'):Scnis->asserclruelSresutooublie funatzion testleforCurcentEnvirdoc h0d->eeeeherueTAGEnactArem ditee sooutwnderAmereyenhensno....
|
81599
|
NULL
|
NULL
|
NULL
|
|
81600
|
2832
|
15
|
2026-05-28T08:31:43.909932+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957103909_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4528724110787610736
|
2604719229101344208
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
iTerm2ShellEditViewSessionScriptsProfilesWindowHelp‹$0A-zshscreenpipe"DOCKERO ₴1DEV (docker)worker-calendar:worker-calendar_00:startedworker-conferences:worker-conferences_00: startedworker-crm-sync:worker-crm-sync_00: startedworker-crm-update:worker-crm-update_00: startedworker-download:worker-download_00:startedworker-emails:worker-emails_00:startedworker-es-update:worker-es-update_00:startedworker-nudges:worker-nudges_00: started₴2-zshО 84-zshWhat's next:Try Docker Debug forLearnseamless, persistentdebugging tools in any container or image → docker debug docker_lamp_1moreat [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.php-v--using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5698/5698 C80100%*5ec2-user@ip-10-30-1...O 86100% <78 • Thu 28 May 11:31:43T81ec2-user@ip-10-30-140-...$7Fixed 0 of 5698 files in 52.731 seconds, 799.06 MB memory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $D...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81599
|
2833
|
15
|
2026-05-28T08:31:25.793080+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957085793_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.40223464},"on_screen":true,"value":"","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2129860785133473404
|
-4704983834769847381
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide
Sync Changes
Hide This Notification
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81597
|
2832
|
14
|
2026-05-28T08:31:24.150359+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779957084150_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-8171751502949769767
|
-5862347367460205653
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Code changed:
Hide...
|
81596
|
NULL
|
NULL
|
NULL
|
|
81485
|
2826
|
34
|
2026-05-28T08:18:16.818706+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956296818_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1764831529811932805
|
-8307856800295171704
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81484
|
2827
|
45
|
2026-05-28T08:18:13.655213+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956293655_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1764831529811932805
|
-8307856800295171704
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81483
|
2826
|
33
|
2026-05-28T08:18:13.551111+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956293551_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-987438372797753690
|
-6438878488507806805
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification...
|
81481
|
NULL
|
NULL
|
NULL
|
|
81482
|
2827
|
44
|
2026-05-28T08:18:10.964729+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956290964_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8043719072324535154
|
-8628527368849355612
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
PhpStormEV faVsco,ls ~Vie Project: faVsco.js, menu
PhpStormEV faVsco,ls ~View$2 JY-20915-fix-missCootRunWindow©InternetMessagelnterface.phy©MailChannelService.phpo Textrelkysewice. oneMeetingGeneratorNotification#OAuth2PlaybooksRecallAl© TextRelayServiceTest.phpStrategyStreaminga TeamTelephonyaUserPilot#Webhook© AbstractService.php©ActivityProviderFactory.php©ActivityService.php© ApiResponseService.phpeeonaraneacarhes oool©InsightSeatService.php© InstantMeetingService.php@ IntercomService.phpE env.productiona, funten rercrenter/remeteSnessage = $service-susers_nessages->get(Smailbox, Snessageld);Sheaders = Snessage->getPayLoad()->getHeaders():SoriginalTo = nutl;Sto = null;1f (Sheader->name• a= "X-6m-Original-To') (} elseif (Sheader->nane uue "To') €Sreciptent = SoriginalTo 2? Sto;1f (Srecipient [== null) 4Smatches = $this->matchesExpectedRecipient(Srecipient, $expectedAlias, $expectedHost)=© Jiminny.phpA SF giminny@localhost][2826-05-28 87:47:50) Local. INFO: Sparans(startHistoryId) => 359021-correlatzon10:%aC0/1105-C2415-4442-17826-85-28 87:47:58 Local.wFu: SnessagchzscoryA console [PROD]# consoe leu.1d":*87f39623-3deb-4827-a8cf-b862acc93289**trace10: [CREDIT_CARD]-a8cт-0862aec93789-17876-85528 87-S8857omuotfteSoamane[historyTypes] => nessageAddedstartHistorytoll50%2"ph67/306-7350-172h-6789-4017456066550 "tлaса 36".-62a0Rp6p-1669-hcR4-h1de-R/3ceccba6at*[2826-85-28 07:50:58] Local.INF0: SnessageHistory{"correlation_id":"ebf74306-735e-472b-D780-f9a7f56e465S*, "trace_1d*:*b2a98e4e-d669-4c04-b1de-843ceçc6a601*}2924-05-28 07-55-17 1 1oc01 THSn• Snanane[nistoryTypes) => nessageAdded(startHistoryId] => 359921-4d4a-b84b-a8531ca414a7*}(2826-05-28 87:SS:12] Local.INF0: SmessageHistory{"correlation_id":"25971837-31f1-431b-ad59-e898eb48b0Sf*, "trace_id*:"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7*}[2826-85-28 08:00:53] Local.INF0: Sparansmistorvnvoes > messageadded[startHistoryid) => 359025connel atson o""naosynoo%ctheyerark -chn chcoaiieuooace aeuei aioowe ser.oSec-hsyiuhichthuierhooR neohieSa oetet shacsadel stomX6c82479-7042-1566.05cc-h529269c24h7m[2826-85-28 88:05:23] Local.INFO: Sparans7o0sLXoo Inu co moy ti-lo.lU TextRelayServiceTest~Cascaderner hensemwiet+0.What about this. Seems the + sign is in email. Wil ti still work and howYes, this will work correctly. Let me trace through the logic with this exact emailo tncader valtos catchen2444700 SyxPorlheeeRoosueonnrcopheM soler onoirt8carchenttocho0LyaPors.cra8808.0o.wot.tdwrinw.conthos,chict:Xwloihy.cos=ssXr9th.os1/ 3. Strip plus tag fron local partstoca Basc= exolodel",catch=a14447700157786...Ol"carch-alt// 4. Compare alías: 'catch-all' ma= 'catch-all' 7 - returns truThen in EnsilTextRelay job, parseRecipient() uses the To header directly and the regex \d+).1d+). [a-zA-20-- the * prefixbelore tne phoné numbers is stripped oy parsekeciotentintoentities wnich prepends + ilselt anyway.Everything works end-to-end. Now you just need to re-apply the to header falliback fix so these messagesice.0ho #l187-718Fix is back in place and the temporary headers oresent disgnostic logging is removed. The tests already retlcctthis logic from earlier. You're good to deploy.Ask anything (XOL)-@ eodtAdhotvKtwodeurlete186:32 UTF-8• C2 4 space:...
|
81479
|
NULL
|
NULL
|
NULL
|
|
81481
|
2826
|
32
|
2026-05-28T08:18:10.862620+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956290862_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpDOCKER₴81DEV ( SlackFileEditViewGoHistoryWindowHelpDOCKER₴81DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up to date for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/‹438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary ofimage vulnerabilities and recommendations docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files perprocess.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78• Thu 28 May 11:18:10Describe what you are looking for* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
NULL
|
8939761280494406748
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpDOCKER₴81DEV ( SlackFileEditViewGoHistoryWindowHelpDOCKER₴81DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up to date for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/‹438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary ofimage vulnerabilities and recommendations docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files perprocess.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78• Thu 28 May 11:18:10Describe what you are looking for* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81480
|
2826
|
31
|
2026-05-28T08:18:00.251289+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956280251_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1764831529811932805
|
-8307856800295171704
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
81477
|
NULL
|
NULL
|
NULL
|
|
81479
|
2827
|
43
|
2026-05-28T08:18:00.149862+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956280149_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1764831529811932805
|
-8307856800295171704
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81478
|
2827
|
42
|
2026-05-28T08:17:50.815333+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956270815_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8043719072324535154
|
-8628527368849355612
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
PhpStorm$2 JY-20915-fix-m Project: faVsco.js, menu
PhpStorm$2 JY-20915-fix-miss©MailChannelService.phpMeetingGeneratorNotification#OAuth2PlaybooksRecallAlStrategyStreaminga TeamTelephonyaUserPilot#Webhook© AbstractService.php©ActivityProviderFactory.php©ActivityService.php©ApiResponseService.phpeeonaraneacarhes oool©InsightSeatService.php© InstantMeetingService.phpCootRunWindow© SyneMailbox.php© TextRelayServiceTest.phpE .env.production3: vane (unetton arereurentenv/romenteSnessage = $service-susers_nessages->get(Smailbox, Snessageld);Sheaders = Snessage->getPayLoad()->getHeaders():SoriginalTo = nutz:lSto = null;1f (Sheader->nameaas Xeol-urzethal-lo1 elseif (Sheader-»nane uns "To") €Sreciptent = SoriginalTo 2? Sto;Lf (Srecipient (== null) 4Smatches = $this->matchesExpectedRecipient(Srecipient, $expectedAlias, $expectedHost)'=© Jiminny.phpA SF giminny@localhost)[2826-05-28 87:47:50) Local. INFO: Sparans(startHistoryId) => 359021-correlatzon10:%aC0/1105-C2415-4442-17826-85-28 87:47:58 Local.wFu: SnessagchzscoryA console [PROD]# consoe leu.1d":*87f39623-3deb-4827-a8cf-b862acc93289**trace10: [CREDIT_CARD]-a8cт-0862aec93789-%17876-85528 87-S8857omuotfteSoamane[historyTypes] => nessageAddedstartHistorytoll50%2"ph67/306-7350-172h-6789-4017456066550 "tлaса 36".-62a0Rp6p-1669-hcR4-h1de-R/3ceccba6at*[2826-85-28 07:50:58] Local.INF0: SnessageHistory{"correlation_id":"ebf74306-735e-472b-b780-f9a7fS6e465S*,"trace_1d":*b2a98e4e-d669-4c04-b1de-843cecc6a601*}2924-05.28 87-55-17 1 1oc01 TNSh: Soanans[nistoryTypes) => nessageAdded(startHistoryId] => 359921-4d4a-b84b-a8531ca414a7*}(2826-05-28 87:SS:12] Local.INF0: SmessageHistory{"correlation_id":"25971837-31f1-431b-ad59-e898eb48b0Sf*, "trace_id*:"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7*}[2826-85-28 08:00:53] Local.INF0: Sparansmistorvivoes => messageadded[startHistoryid) => 359025connel atson o""naosynoo%ctheyerark -chn chcoaiieuooace aeuei aioowe ser.oSec-hsyiuhichthuOierhoR RRohieSaioetst SrassadelsromX6c82470-7042-4566.05cc-h52026Ac24h7"[2826-05-28 88:05:23] Local.INFO: SparansCascaderner hensemwietTO0У L78• Thu 28 May 11:17:50U TextRelayServiceTest~+0.What about this. Seems the + sign is in email. Wll ti still work and howYes, this will work correctly. Let me trace through the logic with this exact emaillo tncader valtos catchen2444700 SyxPorlheeeRoosueonnrcopheM soler onoirt8carchenttocho0LyaPors.cra8808.0o.wot.tdwrinw.conhos,chict:Xwoihnv.cosesX1419thh.os1/ 3. Strip plus tag fron local partstoca Base= exolodel"*,catch=a14447700.57706...e"carch-alt// 4. Compare alías: 'catch-all' ma= 'catch-all' 7 - returns truSo isforcurrentEnvi ronsentü returns tre and the messace docaeds to oe disoatchedThen in EnsilTextRelay job, parseRecipient() uses the To header directly and the regex \8+).1d+).(a-zA-20-- the & prefixbelore tne phoné numbers is stripped oy parsekeciotentintoentities wnich prepends + ilselt anyway.Everything works end-to-end. Now you just need to re-apply the to header falliback fix so these messagesice.0ho #1187-716Fix is back in place and the temporary headers oresent disgnostic logging is removed. The tests already retlcctthis logic from earlier. You're good to deploy.Ask anything (XOL)-@ eodtAdhotvKwoeunate186:32 UTF-8• C2 4 space:...
|
81474
|
NULL
|
NULL
|
NULL
|
|
81477
|
2826
|
30
|
2026-05-28T08:17:50.920103+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956270920_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-8341700080930998891
|
-8235816798443288184
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81476
|
2827
|
41
|
2026-05-28T08:17:31.308113+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956251308_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1764831529811932805
|
-8307856800295171704
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
81474
|
NULL
|
NULL
|
NULL
|
|
81475
|
2826
|
29
|
2026-05-28T08:17:29.184326+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956249184_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1764831529811932805
|
-8307856800295171704
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
81473
|
NULL
|
NULL
|
NULL
|
|
81474
|
2827
|
40
|
2026-05-28T08:17:01.003763+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956221003_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.37632978,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"15","depth":4,"bounds":{"left":0.3856383,"top":0.10055866,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39694148,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40425533,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1764831529811932805
|
-8307856800295171704
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
15
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81473
|
2826
|
28
|
2026-05-28T08:16:58.099313+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956218099_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.019444445,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2797364124384554827
|
-7623060321892881446
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
SlackFileEditViewGoHistoryWindowHelpDOCKER• ₴1DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up todate for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/q438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary of image vulnerabilities and recommendations → docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files per process.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78 • Thu 28 May 11:16:57Describe what you are looking for* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81472
|
2827
|
39
|
2026-05-28T08:16:57.995978+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956217995_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
4195952255238992687
|
-8812277550477751928
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}...
|
81470
|
NULL
|
NULL
|
NULL
|
|
81471
|
2826
|
27
|
2026-05-28T08:16:51.964608+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956211964_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.019444445,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.014583333,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4729423357167171668
|
-8235799205988284024
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
81468
|
NULL
|
NULL
|
NULL
|
|
81470
|
2827
|
38
|
2026-05-28T08:16:51.859578+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956211859_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4729423357167171668
|
-8235799205988284024
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81469
|
2827
|
37
|
2026-05-28T08:16:49.898635+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956209898_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-3150964534923304660
|
-4304507549388960332
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
PhpStormViewCootRurTOOI-WindowFV faVsco.|s ~$ JY-20915-fix-misproidet) Kernelphp© SyncMailbox.phpockhrhtt© InternetMessagelnterface.ph© MailChannelService.phgTextRelayServiceTest.php3.env.productionclass TextRelayServiceo Textrelkysewice.ond MeetingGeneratorda Notificationên OAuth2in Playbooks—KeCaLA—oeownyJ StrategyStreaminga Teama [EMAIL]@ ApiResponseService.ohdCeonarsneasaries oodclineehCaatswies donC InstantMeetingService.phgc IntercomService.phgC IpapiClient.phpc lpapiService.phpC ParticipantShareService.phg© PlanhatService.php© PlaybackService.phpPlaybackVideoOnlyService.pho© PlaybookCategoryService.php© PlaylistGeneratorinterface.php© ResolveTeamCrmConnection.ph© SimoleThrottleService.ohd© SlackService.oho© SoclalAccountService.oho)© SoftPhoneService.oho©) TeamDeactivatedService.oho©) TeamOwnerService.ohoC) TeamService.ohoC) TranscodeParameterResolver.ohCUserService.ohdC Uuidloho> M Traitc@ UseCases181182183uuise ValaationMo halnore nhr@ tnitislGrantondGtnto nho88555852553eillliminnv nhnA Olen nhipobtaeatuuetzondaueysnscogyroangeyeegne seoezeee. 12sservace & schis-serservace suazlooxSwatchRequest = new Google6naiz\WatchRequestoSwatchRequest->setLabelIds(['INB0X'])smechkeoues csstthewecnterwrconcluotSexonrunhisdino= SwatchResponse->expiration / 1000;ShistoryPosint =ointl SwarcheesoonseoshictomydSthis->setHistoryPoint(Stopic, ShistoryPoint);return ShistoryPoint;private function isForCurrentEnvironmentGoogleGnail Sserviceetasnn Chasihaystring SexpectedAliasstring SexpectedHos:): boor ttoy lSnessage = Sservice->users nessages->get(Smailbox, Smessageld)sheaders = saessage->oexrayload ->oecheadersorSoniginalTo = null;Rencetforeach (Sheaders as Sheader)Sif (Sheaden->nane aa= «X-6n-0cfoinal-To") 2Smatches = Sthis->natchesExpectedRecipient(Sheader->value, SexpectedALias.} elseif (Sheader->name aa= 'To') 4nethandon.susimeeSrecipient = Soriginalto ?? Sto:if (Srecipient !as nulb)Snatches = Sthis->matchesExpectedRecipient(Srecipient, SexpectedALias, SexpectedHostv Accept Fle x- X Reject File ox ci4 CnatchesiSF (iminny@localhost)HS.Jocal jiminny@blocalhost)& console [PROD)# consoe leu.2826-85-28 87:47:501 Local.INF0: Sparansnzscorylypes = messageaddecstartHistoryId) => 3599219aC0 //105-02715-4442-3886-12638233809701d":*87f39623-3deb-4827-aBcf-b862acc93289**17826-85-28 87:47:58 Local.wFu: Snessagchzscorytrace10: [CREDIT_CARD]-a8cт-0862aec93789-%17876-85528 87-S8857omuotfteSoamaneIhistorylypes => messageAddecstartHistorytoll50%2*ebf74306-735e-472b-b788-f9a7f56e4655*, "trace_1d":"b2a98e4e-d669-4c84-b1de-843cecc6а681*)2826-85-28 87-58-5811 JocnlTWEn: Snessadels stom{"correlation_id":"ebf74306-735e-472b-b788-f9a7f56e4655*,"trace_1d":"b2a98e4e-d669-4C04-b1de-843cecc6a681"}2924-05.28 87-55-17 1 1oc01 TNSh: SoananshistoryTypes => messageAddecAwAtU&AtAAuTAl = 26002-4d4a-b84b-a8531ca414a7"12826-85-28 87:55:171 Zocal.INF0: SmessageHistory#"correlation_id":"25971837-3141-431b-adS9-e898eb49beSf*, *trace_1d*:*c3463c2c-d21b-4d4a-b84b-a8531ca414a7"}(2826-85-28 88:88:531 Zocal, INF0: SparansArrav[historyTypesl => nessageAddedistartHistoruidl s 350029connel atson o""naosynoo%ctheyerark -chn chcoaiieuooace aeuei aioowe ser.oSec-hsyiuhichthuOierhoR RRohieSaioetst SrassadelsromX6c82479-7042-1566.05cc-h529269c24h7m2924-85.28 9R-95-271 1ocol TМSЛ• Soananeinu cowoy ti-lo.Cascadirner hensewiet+0.Winst about the. Shams the + cion is in emslWitistill work and hownYes, this will work correctly. Let me trace through the logic with this exact ema:oneioerwawue carchswewwoL720onsshwobl.n0o.ktw1oinnv.cos0 pho11 1. Split on €oirdecch- tuewbewtonsehototordoskolotorxrwetnnv.con"I1 2. Host check: 'txt.fiminny.com'11 3. Strip plus tag fron local partcatch-all[PHONE]...e- "catch-all/1 4. Compare alías: 'catch-all' mm 'catch-all' - returns truSo isForcurrentEnvi ronsentü returns true and the messade orocreds to be disoatchedThen in EnaflTextRelay job, parseRecipient() uses the To header directly and the regex \d+\.1d+\. [a-zA-20-- the + prefixoetore tne phone numoers is stipped or parschecipientintoentities, wiuch prepenos + iselt anyway.Everythina worke end-tosand. Now vou luet nesd to ranodly the To Thoader thinrck ir so these mosenaosaren't refused.pho #L182-218haytRelusarich.oorFix is back in place and the temporary headerspresent disgnostic logging is removed. The tests already reflectthis loae trom aartar. Youtre cnodito deoio1tile +23-12>Ask anything (XOL)- @ CodnAdhotvAcceot allKwindeurlahmest4 space...
|
81467
|
NULL
|
NULL
|
NULL
|
|
81468
|
2826
|
26
|
2026-05-28T08:16:49.793362+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956209793_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.019444445,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2797364124384554827
|
-7623060321892881446
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
SlackFileEditViewGoHistoryWindowHelpDOCKERO ₴1DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up todate for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/q438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary of image vulnerabilities and recommendations → docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files per process.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78• Thu 28 May 11:16:49Describe what you are looking for®* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81467
|
2827
|
36
|
2026-05-28T08:16:47.307201+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956207307_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4729423357167171668
|
-8235799205988284024
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81466
|
2827
|
35
|
2026-05-28T08:16:31.901746+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956191901_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-8364568366956037565
|
-8235816729454851704
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project...
|
81465
|
NULL
|
NULL
|
NULL
|
|
81465
|
2827
|
34
|
2026-05-28T08:16:30.609585+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956190609_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4729423357167171668
|
-8235799205988284024
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81464
|
2826
|
25
|
2026-05-28T08:16:30.508036+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956190508_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.019444445,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.014583333,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4729423357167171668
|
-8235799205988284024
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
81463
|
NULL
|
NULL
|
NULL
|
|
81463
|
2826
|
24
|
2026-05-28T08:16:27.496999+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956187496_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-3150964534923304660
|
-4304507549388960332
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
SlackFileEditViewGoHistoryWindowHelpDOCKER• ₴1DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up todate for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/q438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary of image vulnerabilities and recommendations → docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files per process.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78• Thu 28 May 11:16:27Describe what you are looking for* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81462
|
2827
|
33
|
2026-05-28T08:16:25.794078+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956185794_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rapstomCoocWindowFV faVsco.s ~$ JY-20915-fix-missi rapstomCoocWindowFV faVsco.s ~$ JY-20915-fix-missing-header-text-© InternetMessagelnterface.ph© MailChannelService.phg0 MeetinaGeneratoromcadonEOHUNDn PlaybooksJotaeoa Teama Telechony#UserPilotWebhookC Abstrac Semvice cho©ActivitvProviderFactory.oho© ActivityService.php© ApiResponseService.ohoCeonarsneasaries oodg InsightSeatService.phpC InstantMeetingService.phpcilntecomswneoeC IpapiClient.php© IpapiService.phpC ParticipantShareService.phg©. PlanhatService.php© PlaybackService.phpPlaybackVideoOnlyService.pho© PlaybookCategoryService.php© PlaylistGeneratorinterface.phpel PocAlvoTosmErmEmЛodiA ny© SimoleThrottleService.ohg© SlackService.ohdC SocialAccountService.oho)C SoftPhoneService.oho©) TeamOwnerService.ohoC) TeamService.ohoC) TranscodeParameterResolver.ohC UserSemce.on©Uuid.php> M Traitc@ UseCasese ValaationMo halnore nhr@ tnitislGrantondGtnto nhoelliminnv nhamockhrhtsTextRelayServiceTest.php3.env.productionclass TextRelayServiceouoere Tuncczon syne diidAAAAUIUTTTASSnazloox & contzol xeyanny,coogle texc userSexpectedAlias = config(key. 'jiminny.deploy region') =a= 'eu' ? "catch-all-eu' : 'catch-all''(TextRelavSeryicel Stanttina svnc'."MexoeCro mous EXSeXoeCeohee>exoccreohosSsenwice e Sthis->ae-Semuicetstaslbox)SmessageHistory = Sthis->getHistory(Sservice):aulunznace suopore racades Loa::channel-cuscon channel ->intolSnessagchase AcceotSmessageIds = 0:foreach (SnessageHistory as Shistories) {Snessages = Shistories->messagesAdded ?? 0:foreach (Smessages as Smessage)Snessageld = Smessage-snessage->idif ( Sthis->isForQurrentEnvironnent(Sservice, Snallbox, Snessageld, SexoectedAlias.Norowoeroesss0eosrsosSf (ScelavedText === null)ScelavedText = TextRelave:createrfemaa orouidert e> Texthelay.eproumer ostare"emaennouider o s> Shesssoeld.satus' E Textee hy.STATS PRodEsSiNGSiob = new Emai TextRelay(Snessageld, Srelayediext):ahesonthouoteuCanctanternEit MATGoeon chil100dispatch(Siob):Loo:sinfo( messace: "(TextRelavService) Successfully dispatched nessage"nessago id/ pa snsse ice na xaX Reject File oxesr uim nnye rocolnost& console [PROD# consoe leu.cozo"os"lo 01.4/.00 Locat.nr. godidushistoryTypes => messageAddec(startHistoryId) => 359921correlazon1d:YaC0//105-c215-4442-2886-7269823580901trace_1d*: *87f39623-3deb-4827-a8cf-b862aec93289**7826-85-28 87:47:58 Local.IWFU: SnessagchzscomvoTrace10: [CREDIT_CARD]-a8cт-0862aec93789-17876-85528 87-S8857omuotfteSoamaneIhistorylypes => messageAddecstartHistorytoll50%2{"correlation_id":"ebf74386-735e-472b-b788-f9a7f56e4655*,*trace_1d*:"b2a98e4e-d669-4c84-b1de-843cecc6a681")2826-85-28 R7-59-5811 1oclTNED: Snessadels stomuEconnelatton Saw."ehf71z0h-775a.170h-h780.40.7456e01550 "ьласA S/.-6290R0/9-1640-6604-h1de-9/3cecchaf91»)2924-85.28 87-55-17 | 1o601 TNEh• SoananshistoryTypes => messageAddecAwAtU&AtAAuTAl = 26002-4d4a-b84b-a8531ca414a7"1300x.06.2992-66-17| Jocol-Twet: Snossagchs stom.#"correlation_id":"25971837-3161-431b-adS9-e898eb49beSf*, *trace_1d*:*c3463c2c-d21b-4d4a-b84b-a8531ca614a7"}(2826-85-28 88:88:531 Zocal, INF0: Sparansmistorvnvoes => nessagenddedistartHistorvidl s 350925connel atson o""naosynoo%ctheyerark -chn chcoaiieuooace aeuei aioowe ser.oSec-hsyiuhichthuOierhoR RRohieSaioetst Srassadelsrom#[CREDIT_CARD].05cc-H529269c24h7"2924-85-28 AR-95-27| Toeol TNSh: Soananeoo inu co moy tirloiceeeendhOTXCONHENYSWWIC+0.Winst about the. Shams the + cion is in emslWitistill work and hownYes, this will work correctly. Let me trace through the logic with this exact ema:oneioerwilue carchswe/woL7o0orsshoobl.rdowkhtwer1ohnnv.co0 pho11 1. Split on €oirdeccheateeobewtonehoturdos kolotorxrwehtnnv.cos"I1 2. Host check: 'txt.fiminny.com"11 3. Strip plus tag fron local partcatch-all[PHONE]..11 - 'catch-all/1 4. Compare alías: 'catch-all' mm 'catch-all' - returns truSo isForcurrentEnvi ronsentl returns true and the messade orocreos to be disoatchedThen in EnaflTextRelay job, parseRecipient() uses the To header directly and the regex \d+\.1d+\. [a-zA-20-- the + prefixoetore tne phone numoers is stipped or parschecipientintoentities, wiich prepenos + iselt anyway.Everythina worke end-tosand. Now vou luet nesd to ranodly the To Thoader thinrck ir so these mosenaosaren't refused.vice.pho #L182-210haytRelusarich.oor1tile +24-15>Ask anything (XOL)" HodhAdhotvAcceot all• OKwindeurlahmeht4 spad...
|
NULL
|
6843649552266690491
|
NULL
|
click
|
ocr
|
NULL
|
rapstomCoocWindowFV faVsco.s ~$ JY-20915-fix-missi rapstomCoocWindowFV faVsco.s ~$ JY-20915-fix-missing-header-text-© InternetMessagelnterface.ph© MailChannelService.phg0 MeetinaGeneratoromcadonEOHUNDn PlaybooksJotaeoa Teama Telechony#UserPilotWebhookC Abstrac Semvice cho©ActivitvProviderFactory.oho© ActivityService.php© ApiResponseService.ohoCeonarsneasaries oodg InsightSeatService.phpC InstantMeetingService.phpcilntecomswneoeC IpapiClient.php© IpapiService.phpC ParticipantShareService.phg©. PlanhatService.php© PlaybackService.phpPlaybackVideoOnlyService.pho© PlaybookCategoryService.php© PlaylistGeneratorinterface.phpel PocAlvoTosmErmEmЛodiA ny© SimoleThrottleService.ohg© SlackService.ohdC SocialAccountService.oho)C SoftPhoneService.oho©) TeamOwnerService.ohoC) TeamService.ohoC) TranscodeParameterResolver.ohC UserSemce.on©Uuid.php> M Traitc@ UseCasese ValaationMo halnore nhr@ tnitislGrantondGtnto nhoelliminnv nhamockhrhtsTextRelayServiceTest.php3.env.productionclass TextRelayServiceouoere Tuncczon syne diidAAAAUIUTTTASSnazloox & contzol xeyanny,coogle texc userSexpectedAlias = config(key. 'jiminny.deploy region') =a= 'eu' ? "catch-all-eu' : 'catch-all''(TextRelavSeryicel Stanttina svnc'."MexoeCro mous EXSeXoeCeohee>exoccreohosSsenwice e Sthis->ae-Semuicetstaslbox)SmessageHistory = Sthis->getHistory(Sservice):aulunznace suopore racades Loa::channel-cuscon channel ->intolSnessagchase AcceotSmessageIds = 0:foreach (SnessageHistory as Shistories) {Snessages = Shistories->messagesAdded ?? 0:foreach (Smessages as Smessage)Snessageld = Smessage-snessage->idif ( Sthis->isForQurrentEnvironnent(Sservice, Snallbox, Snessageld, SexoectedAlias.Norowoeroesss0eosrsosSf (ScelavedText === null)ScelavedText = TextRelave:createrfemaa orouidert e> Texthelay.eproumer ostare"emaennouider o s> Shesssoeld.satus' E Textee hy.STATS PRodEsSiNGSiob = new Emai TextRelay(Snessageld, Srelayediext):ahesonthouoteuCanctanternEit MATGoeon chil100dispatch(Siob):Loo:sinfo( messace: "(TextRelavService) Successfully dispatched nessage"nessago id/ pa snsse ice na xaX Reject File oxesr uim nnye rocolnost& console [PROD# consoe leu.cozo"os"lo 01.4/.00 Locat.nr. godidushistoryTypes => messageAddec(startHistoryId) => 359921correlazon1d:YaC0//105-c215-4442-2886-7269823580901trace_1d*: *87f39623-3deb-4827-a8cf-b862aec93289**7826-85-28 87:47:58 Local.IWFU: SnessagchzscomvoTrace10: [CREDIT_CARD]-a8cт-0862aec93789-17876-85528 87-S8857omuotfteSoamaneIhistorylypes => messageAddecstartHistorytoll50%2{"correlation_id":"ebf74386-735e-472b-b788-f9a7f56e4655*,*trace_1d*:"b2a98e4e-d669-4c84-b1de-843cecc6a681")2826-85-28 R7-59-5811 1oclTNED: Snessadels stomuEconnelatton Saw."ehf71z0h-775a.170h-h780.40.7456e01550 "ьласA S/.-6290R0/9-1640-6604-h1de-9/3cecchaf91»)2924-85.28 87-55-17 | 1o601 TNEh• SoananshistoryTypes => messageAddecAwAtU&AtAAuTAl = 26002-4d4a-b84b-a8531ca414a7"1300x.06.2992-66-17| Jocol-Twet: Snossagchs stom.#"correlation_id":"25971837-3161-431b-adS9-e898eb49beSf*, *trace_1d*:*c3463c2c-d21b-4d4a-b84b-a8531ca614a7"}(2826-85-28 88:88:531 Zocal, INF0: Sparansmistorvnvoes => nessagenddedistartHistorvidl s 350925connel atson o""naosynoo%ctheyerark -chn chcoaiieuooace aeuei aioowe ser.oSec-hsyiuhichthuOierhoR RRohieSaioetst Srassadelsrom#[CREDIT_CARD].05cc-H529269c24h7"2924-85-28 AR-95-27| Toeol TNSh: Soananeoo inu co moy tirloiceeeendhOTXCONHENYSWWIC+0.Winst about the. Shams the + cion is in emslWitistill work and hownYes, this will work correctly. Let me trace through the logic with this exact ema:oneioerwilue carchswe/woL7o0orsshoobl.rdowkhtwer1ohnnv.co0 pho11 1. Split on €oirdeccheateeobewtonehoturdos kolotorxrwehtnnv.cos"I1 2. Host check: 'txt.fiminny.com"11 3. Strip plus tag fron local partcatch-all[PHONE]..11 - 'catch-all/1 4. Compare alías: 'catch-all' mm 'catch-all' - returns truSo isForcurrentEnvi ronsentl returns true and the messade orocreos to be disoatchedThen in EnaflTextRelay job, parseRecipient() uses the To header directly and the regex \d+\.1d+\. [a-zA-20-- the + prefixoetore tne phone numoers is stipped or parschecipientintoentities, wiich prepenos + iselt anyway.Everythina worke end-tosand. Now vou luet nesd to ranodly the To Thoader thinrck ir so these mosenaosaren't refused.vice.pho #L182-210haytRelusarich.oor1tile +24-15>Ask anything (XOL)" HodhAdhotvAcceot all• OKwindeurlahmeht4 spad...
|
81459
|
NULL
|
NULL
|
NULL
|
|
81461
|
2826
|
23
|
2026-05-28T08:16:25.691166+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956185691_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpDOCKER• ₴1DEV SlackFileEditViewGoHistoryWindowHelpDOCKER• ₴1DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up todate for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/q438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary of image vulnerabilities and recommendations → docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files per process.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78• Thu 28 May 11:16:25Describe what you are looking for* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
NULL
|
1854427488783385704
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpDOCKER• ₴1DEV SlackFileEditViewGoHistoryWindowHelpDOCKER• ₴1DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up todate for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/q438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary of image vulnerabilities and recommendations → docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files per process.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78• Thu 28 May 11:16:25Describe what you are looking for* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
81460
|
NULL
|
NULL
|
NULL
|
|
81460
|
2826
|
22
|
2026-05-28T08:16:23.558532+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956183558_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.019444445,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.014583333,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n $originalTo = null;\n $to = null;\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $originalTo = $header->value;\n } elseif ($header->name === 'To') {\n $to = $header->value;\n }\n }\n\n $recipient = $originalTo ?? $to;\n\n if ($recipient !== null) {\n $matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedRecipient = explode('+', $recipient)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedRecipient,\n ]);\n }\n\n return $matches;\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [\n 'message_id' => $messageId,\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7456676975688765609
|
-6438878488507806805
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
$originalTo = null;
$to = null;
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$originalTo = $header->value;
} elseif ($header->name === 'To') {
$to = $header->value;
}
}
$recipient = $originalTo ?? $to;
if ($recipient !== null) {
$matches = $this->matchesExpectedRecipient($recipient, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedRecipient = explode('+', $recipient)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedRecipient,
]);
}
return $matches;
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To and To headers', [
'message_id' => $messageId,
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81459
|
2827
|
32
|
2026-05-28T08:16:04.643710+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956164643_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
327918965576722946
|
-3660159508063819383
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81458
|
2827
|
31
|
2026-05-28T08:15:51.476969+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956151476_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4060176888399009113
|
-9212323791225028208
|
typing_pause
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
PhpStormViewNeweNNCCoocKetuciolool.WindowFV faVsco.|s ~$2 JY-20915-fix-missing-header-text-relaproideta Kemnelonip© SyncMailbox.phpWockhrhta© InternetMessagelnterface.ph© MailChannelService.phgTextRelayServiceTest.phpo Textrelkysewice.on0 MeetinaGeneratoomcadonên OAuth2Dn Playbooks178—KeCaLAJotaeoDn Streamingla Teama Telechony#UserPilotWebhookC Abstrac Semvice cho©ActivityProviderFactory.php© ActivityService.php© ApiResponseService.oho187188189190Ceonarsneasaries oodg InsightSeatService.phpC InstantMeetingService.phgcilntecomswneoeC IpapiClient.php© IpapiService.phpC ParticipantShareService.phg©. PlanhatService.php© PlaybackService.phpPlaybackVideoOnlyService.pho© PlaybookCategoryService.php© PlaylistGeneratorinterface.php© ResolveTeamCrmConnection.ph© SimoleThrottleService.ohdC SlackService.ohoC SocialAccountService.ohoC SoftPhoneService.oho19319419S ©) TeamOwnerService.ohoC) TeamService.oho213C) TranscodeParameterResolver.o 215C UserSemce.onC Uuidloho> M Traitc› @ UseCasesiMusAUtils>E Va cation215218Mo halnore nhr@ tnitislGrantondGtnto nhoeillliminnv nhnA Olen nhí3.env.productionclass TextRelayServiceivare tuncczon asroncurehichvarohaehtsercoousens nos morooreoox.hesodsmesshad->aerP.w.ondiol->oc-headeneorheaders as Sheader) 1eader->name === "X-6n-0riginal-To')tatches=Sthis->natchessxnectedPecsinent/SheaderswallueSexoectedAbias.Sexoecterhostr((!Smatches) ?Sanitize PIl by renoving plus-tag content for loggingSsanitizedOriginalto = explode( separator: *+*, Sheader->value)(0)=Log::info( message:' TextRelayService) Refused message','message id' => Snessageid,'original to sanitized' a› SsanitizedoriginaltoI):nol messase:Tex kelayservice Kerused nessace: eissing x-on-Urzoznal-To headen"oc10 = Snessagclorspresent' => array_nap(fn (Sh) => Sh->nane . *:• . explode( separator: *+*. Sh->value)(e A(messaoe: "[TextRelavServicel Failed to insoect ressaac*. flge_id' => Smessageldtion' = Se->aetMessageo)anwure syceor lone"atchesExpectedReciplent(string Sreciplent, string SexpectedAlias, string SexpectedHost: bool...1 edit+v Accept Fle x- X Reject File ox cSF fiminny@localhost)HS.Jocal jiminny@blocalhost)2826-85-28 87:47:501 Local.INF0: Sparansnzscorylypes = nessageaddeestartHistoryId) => 359921correlazon1d:YaC0//105-c215-4442-8886-72698253309017826-85-28 87:47:58 Local.wFu: Snessagchzscory& console [PROD)& console (EU1d":*87f39623-3deb-4827-a8cf-b862acc93289*}trace10: [CREDIT_CARD]-a8cт-0862aec93789-%17876-85528 87-S8857omuotfteSoamaneIhistorylypes => messageAddecstartHistorytoll50%2"correlation_id":"ebf74306-735e-472b-b788-f9a7f56e4655*,"trace_1d":"b2a98e4e-d669-4C84-b1de-843cecc6a681*)2826-85-28 87-58-5811 JocnlTWEn: Snessadels stomEconnelatton Saw."ehf71z0h-775a.170h-h780.40.7456e01550 "tлaCA S/.-6290R0/9-1640-hc04-h1de-9/3cecchaf91»)2924-85.28 87-55-17 | 1o601 TNEh• SoananshistoryTypes => messageAddecAwAtU&AtAAuTAl = 26002-4d4a-b84b-a8531ca414a7"1300x.06.29 92.66-17 1 1oc0-051: Snossaachstom."correlation_id":"25971837-3161-431b-adS9-e898eb48bASf* *trace_id*:*c3463c2c-d21b-4d4a-b84b-a8531ca414a7*}(2826-85-28 88:88:531 Zocal, INF0: Sparansmistorvivoes => messageaddedistartHistorvidl s 350925connel atson o""naosynoo%ctheyerark -chn chcoaiieuooace aeuei aioowe ser.oSec-hsyiuhichthuOierhoR RRohieSaioetst Srassadelsrom#[CREDIT_CARD].05cc-H529269c24h7"2924-85-28 AR-95-27| Toeol TNSh: Soananeanler herseietS0100% 142-• Thu 28 May 11:15:51TextRelayServiceTest+0.Winat about thit. Saeme the a sion ie in cmall. Witistill work and howaAsk anything (XOL)—@ eodeAdhotvAReinctalAccoot allXwodeurlhimewrekhirest4 space...
|
81456
|
NULL
|
NULL
|
NULL
|
|
81457
|
2826
|
21
|
2026-05-28T08:15:51.274643+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956151274_m1.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7635200922161528077
|
-4598385934329243181
|
typing_pause
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
SlackFileEditViewGoHistoryWindowHelpDOCKER• ₴1DEV (docker)₴2-zshscreenpipe"Digest:sha256:d6b7ebd9b71c0480b909d77fceada3df720c6594e4c853228765509b36f52db6Status: Imageis up todate for 438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/q438740370364.dkr.ecr.us-east-2.amazonaws.com/jiminny/app/qa:arm64v8-latestWhat's next:View a summary of image vulnerabilities and recommendations → docker scoutquickviewlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-docker exec -it docker_lamp_1 ./vendor/bin/php-cs-fixer fix--config=.php-cs-fixer.dist.plPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminskiand contributors.PHP runtime: 8.5.5Loadedconfigdefault from ".php-cs-fixer.dist.php"Running analysis on 7cores with 10files per process.5698/5698100%1) app/Services/Mail/TextRelayService.php (statement_indentation)begin diff/home/jiminny/app/Services/Mail/TextRelayService.php+++/home/jiminny/app/Services/Mail/TextRelayService.php-67,7 +67,7 @eSjob = new EmailTextRelay(SmessageId, SrelayedText);Sjob-›onQueue(Constants: :QUEUE_EMAILS);dispatch($job);dispatch($job);Log: :info(' [TextRelayService]Successfully dispatched message', ["message_id'= SmessageId,end diffFixed 1 of 5698 files in 84.046 seconds, 701.18 MBmemory usedDetected deprecations in use (they will stop working in next major release)- Rule set"@PHP74Migration" is deprecated. Use"@PHP7x4Migration"instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Rule set "@PHP83Migration" is deprecated. Use "@PHP8x3Migration"instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any containeror image »Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-• •HomeDMsActivityFilesLater..•More+ED→Jiminny... vw Starrea& platform-backend-...platform-inner-teamChannels# ai-chapter# alerts# backend# bugs# confusion-clinic# donut_time# engineering# general# happy_birthday# jbu-team-info# jiminny-bg# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of_jimi...• Direct messages& Petko Kashinski% Galya Dimitrova&. Stefka Stoyanova: Todor StamatovStalivan Ganraiou100% <78• Thu 28 May 11:15:51Describe what you are looking for* & platform-inner-team& 106 0• MessagesP Channel OverviewMore v+Yesterday ~Resolve rrir v.oiotPreview in SlackStatusBacklogPriority= MediumAssigneeUnassignedAs of yesterday at 6:20 PM RefreshOpen in Jira*+ SummarizeToday ~NewNikolay Nikolov 10:52 AMФикс за пускане на remote commands за staging:https://github.com/jiminny/app/pull/12132#12132 Fix stage profile for remote commandsrunJIRA: JY-XXXXDeployment notes:• NoneComments1V1jiminny/app| May 26th Added by GitHubMessage & platform-inner-team...
|
81450
|
NULL
|
NULL
|
NULL
|
|
81456
|
2827
|
30
|
2026-05-28T08:15:50.442577+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956150442_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6234231735877047162
|
-4200521094587332216
|
typing_pause
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
81455
|
2827
|
29
|
2026-05-28T08:15:48.546944+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956148546_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1908413605128525314
|
-3732217102101747319
|
typing_pause
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All...
|
81454
|
NULL
|
NULL
|
NULL
|
|
81454
|
2827
|
28
|
2026-05-28T08:15:45.087226+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779956145087_m2.jpg...
|
PhpStorm
|
faVsco.js – TextRelayService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20915-fix-missing-header-text-relay, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.09740692,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20915-fix-missing-header-text-relay","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"17","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00930851,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Mail;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Component\\Queue\\Constants;\nuse Jiminny\\Jobs\\Mailbox\\EmailTextRelay;\nuse Jiminny\\Models\\TextRelay;\nuse Google\\Service\\Gmail as GoogleGmail;\n\nclass TextRelayService\n{\n public function __construct()\n {\n $credentials = storage_path('text-relay.json');\n\n abort_unless(file_exists($credentials), 422);\n\n putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);\n }\n\n /**\n * Fetch the latest messages since the last sync.\n */\n public function sync(): array\n {\n $mailbox = config('jiminny.google_text_user');\n\n $expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';\n $expectedHost = config('jiminny.google_text_host');\n\n Log::info('[TextRelayService] Starting sync', [\n 'mailbox' => $mailbox,\n 'expected_alias' => $expectedAlias,\n 'expected_host' => $expectedHost,\n ]);\n\n $service = $this->getService($mailbox);\n\n $messageHistory = $this->getHistory($service);\n $messageIds = [];\n\n foreach ($messageHistory as $histories) {\n $messages = $histories->messagesAdded ?? [];\n\n foreach ($messages as $message) {\n $messageId = $message->message->id;\n\n if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {\n continue;\n }\n\n $relayedText = TextRelay::where('email_provider_id', $messageId)->first();\n\n if ($relayedText === null) {\n $relayedText = TextRelay::create([\n 'email_provider' => TextRelay::PROVIDER_GSUITE,\n 'email_provider_id' => $messageId,\n 'status' => TextRelay::STATUS_PROCESSING,\n ]);\n }\n\n $job = new EmailTextRelay($messageId, $relayedText);\n $job->onQueue(Constants::QUEUE_EMAILS);\n\n dispatch($job);\n\n Log::info('[TextRelayService] Successfully dispatched message', [\n 'message_id' => $messageId,\n 'text_relay_id' => $relayedText->id,\n 'queue' => Constants::QUEUE_EMAILS,\n ]);\n\n $messageIds[] = $messageId;\n }\n }\n\n Log::info('[TextRelayService] Sync completed', [\n 'mailbox' => $mailbox,\n 'messages_processed' => count($messageIds),\n 'message_ids' => array_slice($messageIds, 0, 10),\n ]);\n\n return $messageIds;\n }\n\n public function getHistory(GoogleGmail $service): array\n {\n $pageToken = null;\n $topic = config('jiminny.google_text_relay_topic');\n $messages = [];\n $historyId = \\Cache::get($topic);\n\n // If we have no history stored, WatchMailboxEvents must not have run yet :/\n if ($historyId == false) {\n $historyId = $this->refreshHistoryPoint($topic);\n }\n\n $params = [\n 'historyTypes' => 'messageAdded',\n 'startHistoryId' => $historyId,\n ];\n\n do {\n try {\n if ($pageToken) {\n $params['pageToken'] = $pageToken;\n }\n\n $historyResponse = $service->users_history->listUsersHistory(\n config('jiminny.google_text_user'),\n $params\n );\n\n $this->setHistoryPoint($topic, (int) $historyResponse->historyId);\n\n if ($historyResponse->getHistory()) {\n $messages = array_merge($messages, $historyResponse->getHistory());\n $pageToken = $historyResponse->getNextPageToken();\n }\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to fetch Gmail history', [\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n } while ($pageToken);\n\n return $messages;\n }\n\n protected function setHistoryPoint(string $topic, int $historyPoint): Carbon\n {\n $expiresAt = now()->addDay();\n\n \\Cache::put($topic, $historyPoint, $expiresAt);\n\n return $expiresAt;\n }\n\n public function getService(string $mailbox): GoogleGmail\n {\n $client = new \\Google_Client();\n $client->useApplicationDefaultCredentials();\n $client->addScope(GoogleGmail::GMAIL_MODIFY);\n $client->setAccessType('offline');\n $client->setSubject($mailbox);\n\n return new GoogleGmail($client);\n }\n\n public function refreshHistoryPoint(string $topic): int\n {\n $mailbox = config('jiminny.google_text_user');\n $service = $this->getService($mailbox);\n\n $watchRequest = new GoogleGmail\\WatchRequest();\n $watchRequest->setLabelIds(['INBOX']);\n $watchRequest->setLabelFilterAction('include');\n $watchRequest->setTopicName($topic);\n\n $watchResponse = $service->users->watch($mailbox, $watchRequest);\n\n //$expiryTimestamp = $watchResponse->expiration / 1000;\n $historyPoint = (int) $watchResponse->historyId;\n\n $this->setHistoryPoint($topic, $historyPoint);\n\n return $historyPoint;\n }\n\n private function isForCurrentEnvironment(\n GoogleGmail $service,\n string $mailbox,\n string $messageId,\n string $expectedAlias,\n string $expectedHost\n ): bool {\n try {\n $message = $service->users_messages->get($mailbox, $messageId);\n $headers = $message->getPayload()->getHeaders();\n\n foreach ($headers as $header) {\n if ($header->name === 'X-Gm-Original-To') {\n $matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);\n\n if (! $matches) {\n // Sanitize PII by removing plus-tag content for logging\n $sanitizedOriginalTo = explode('+', $header->value)[0];\n Log::info('[TextRelayService] Refused message', [\n 'message_id' => $messageId,\n 'original_to_sanitized' => $sanitizedOriginalTo,\n ]);\n }\n\n return $matches;\n }\n }\n\n Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [\n 'message_id' => $messageId,\n 'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),\n ]);\n } catch (\\Exception $e) {\n Log::error('[TextRelayService] Failed to inspect message', [\n 'message_id' => $messageId,\n 'exception' => $e->getMessage(),\n ]);\n \\Sentry::captureException($e);\n }\n\n return false;\n }\n\n private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool\n {\n $parts = explode('@', $recipient, 2);\n\n if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {\n return false;\n }\n\n $localBase = explode('+', $parts[0], 2)[0];\n\n return strcasecmp($localBase, $expectedAlias) === 0;\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.7293883,"top":0.10055866,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","depth":4,"bounds":{"left":0.43051863,"top":0.09736632,"width":0.32280585,"height":0.90263367},"on_screen":true,"value":"[2026-05-28 07:47:50] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:47:50] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"9acc7103-e275-4442-a80e-72ca0233ad9d\",\"trace_id\":\"87f39623-3deb-4827-a0cf-b862aec93209\"}\n[2026-05-28 07:50:57] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:50:58] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"ebf74306-735e-472b-b780-f9a7f56e4655\",\"trace_id\":\"b2a98e4e-d669-4c04-b1de-043cecc6a601\"}\n[2026-05-28 07:55:17] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359021\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 07:55:17] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"25971837-31f1-431b-ad59-e890eb40b05f\",\"trace_id\":\"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7\"}\n[2026-05-28 08:00:53] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:00:54] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"da957797-f328-4bf7-8a33-961c0cca120c\",\"trace_id\":\"34c82f30-39f2-45cf-95cc-b520260c2fb3\"}\n[2026-05-28 08:05:23] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:05:24] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"c5339dcc-46c1-45a4-81f9-ede0203ab266\",\"trace_id\":\"627196cf-0a09-465a-ab3e-10e546adfcde\"}\n[2026-05-28 08:10:44] local.INFO: $params \nArray\n(\n [historyTypes] => messageAdded\n [startHistoryId] => 359025\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}\n[2026-05-28 08:10:44] local.INFO: $messageHistory \nArray\n(\n)\n {\"correlation_id\":\"8667713e-79c8-46a6-b5a4-b13351d287da\",\"trace_id\":\"52ec740a-b685-4b96-abda-8e5ab1057ea6\"}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
327918965576722946
|
-3660159508063819383
|
typing_pause
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20915-fix-missing-head Project: faVsco.js, menu
JY-20915-fix-missing-header-text-relay, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
1
17
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Jiminny\Component\Queue\Constants;
use Jiminny\Jobs\Mailbox\EmailTextRelay;
use Jiminny\Models\TextRelay;
use Google\Service\Gmail as GoogleGmail;
class TextRelayService
{
public function __construct()
{
$credentials = storage_path('text-relay.json');
abort_unless(file_exists($credentials), 422);
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $credentials);
}
/**
* Fetch the latest messages since the last sync.
*/
public function sync(): array
{
$mailbox = config('jiminny.google_text_user');
$expectedAlias = config('jiminny.deploy_region') === 'eu' ? 'catch-all-eu' : 'catch-all';
$expectedHost = config('jiminny.google_text_host');
Log::info('[TextRelayService] Starting sync', [
'mailbox' => $mailbox,
'expected_alias' => $expectedAlias,
'expected_host' => $expectedHost,
]);
$service = $this->getService($mailbox);
$messageHistory = $this->getHistory($service);
$messageIds = [];
foreach ($messageHistory as $histories) {
$messages = $histories->messagesAdded ?? [];
foreach ($messages as $message) {
$messageId = $message->message->id;
if (! $this->isForCurrentEnvironment($service, $mailbox, $messageId, $expectedAlias, $expectedHost)) {
continue;
}
$relayedText = TextRelay::where('email_provider_id', $messageId)->first();
if ($relayedText === null) {
$relayedText = TextRelay::create([
'email_provider' => TextRelay::PROVIDER_GSUITE,
'email_provider_id' => $messageId,
'status' => TextRelay::STATUS_PROCESSING,
]);
}
$job = new EmailTextRelay($messageId, $relayedText);
$job->onQueue(Constants::QUEUE_EMAILS);
dispatch($job);
Log::info('[TextRelayService] Successfully dispatched message', [
'message_id' => $messageId,
'text_relay_id' => $relayedText->id,
'queue' => Constants::QUEUE_EMAILS,
]);
$messageIds[] = $messageId;
}
}
Log::info('[TextRelayService] Sync completed', [
'mailbox' => $mailbox,
'messages_processed' => count($messageIds),
'message_ids' => array_slice($messageIds, 0, 10),
]);
return $messageIds;
}
public function getHistory(GoogleGmail $service): array
{
$pageToken = null;
$topic = config('jiminny.google_text_relay_topic');
$messages = [];
$historyId = \Cache::get($topic);
// If we have no history stored, WatchMailboxEvents must not have run yet :/
if ($historyId == false) {
$historyId = $this->refreshHistoryPoint($topic);
}
$params = [
'historyTypes' => 'messageAdded',
'startHistoryId' => $historyId,
];
do {
try {
if ($pageToken) {
$params['pageToken'] = $pageToken;
}
$historyResponse = $service->users_history->listUsersHistory(
config('jiminny.google_text_user'),
$params
);
$this->setHistoryPoint($topic, (int) $historyResponse->historyId);
if ($historyResponse->getHistory()) {
$messages = array_merge($messages, $historyResponse->getHistory());
$pageToken = $historyResponse->getNextPageToken();
}
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to fetch Gmail history', [
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
} while ($pageToken);
return $messages;
}
protected function setHistoryPoint(string $topic, int $historyPoint): Carbon
{
$expiresAt = now()->addDay();
\Cache::put($topic, $historyPoint, $expiresAt);
return $expiresAt;
}
public function getService(string $mailbox): GoogleGmail
{
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(GoogleGmail::GMAIL_MODIFY);
$client->setAccessType('offline');
$client->setSubject($mailbox);
return new GoogleGmail($client);
}
public function refreshHistoryPoint(string $topic): int
{
$mailbox = config('jiminny.google_text_user');
$service = $this->getService($mailbox);
$watchRequest = new GoogleGmail\WatchRequest();
$watchRequest->setLabelIds(['INBOX']);
$watchRequest->setLabelFilterAction('include');
$watchRequest->setTopicName($topic);
$watchResponse = $service->users->watch($mailbox, $watchRequest);
//$expiryTimestamp = $watchResponse->expiration / 1000;
$historyPoint = (int) $watchResponse->historyId;
$this->setHistoryPoint($topic, $historyPoint);
return $historyPoint;
}
private function isForCurrentEnvironment(
GoogleGmail $service,
string $mailbox,
string $messageId,
string $expectedAlias,
string $expectedHost
): bool {
try {
$message = $service->users_messages->get($mailbox, $messageId);
$headers = $message->getPayload()->getHeaders();
foreach ($headers as $header) {
if ($header->name === 'X-Gm-Original-To') {
$matches = $this->matchesExpectedRecipient($header->value, $expectedAlias, $expectedHost);
if (! $matches) {
// Sanitize PII by removing plus-tag content for logging
$sanitizedOriginalTo = explode('+', $header->value)[0];
Log::info('[TextRelayService] Refused message', [
'message_id' => $messageId,
'original_to_sanitized' => $sanitizedOriginalTo,
]);
}
return $matches;
}
}
Log::warning('[TextRelayService] Refused message: missing X-Gm-Original-To header', [
'message_id' => $messageId,
'headers_present' => array_map(fn ($h) => $h->name . ': ' . explode('+', $h->value)[0], $headers),
]);
} catch (\Exception $e) {
Log::error('[TextRelayService] Failed to inspect message', [
'message_id' => $messageId,
'exception' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return false;
}
private function matchesExpectedRecipient(string $recipient, string $expectedAlias, string $expectedHost): bool
{
$parts = explode('@', $recipient, 2);
if (count($parts) !== 2 || strcasecmp($parts[1], $expectedHost) !== 0) {
return false;
}
$localBase = explode('+', $parts[0], 2)[0];
return strcasecmp($localBase, $expectedAlias) === 0;
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
6
Previous Highlighted Error
Next Highlighted Error
[2026-05-28 07:47:50] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:47:50] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"9acc7103-e275-4442-a80e-72ca0233ad9d","trace_id":"87f39623-3deb-4827-a0cf-b862aec93209"}
[2026-05-28 07:50:57] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:50:58] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"ebf74306-735e-472b-b780-f9a7f56e4655","trace_id":"b2a98e4e-d669-4c04-b1de-043cecc6a601"}
[2026-05-28 07:55:17] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359021
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 07:55:17] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"25971837-31f1-431b-ad59-e890eb40b05f","trace_id":"c3f63c2c-d21b-4d4a-b84b-a8531ca414a7"}
[2026-05-28 08:00:53] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:00:54] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"da957797-f328-4bf7-8a33-961c0cca120c","trace_id":"34c82f30-39f2-45cf-95cc-b520260c2fb3"}
[2026-05-28 08:05:23] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:05:24] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"c5339dcc-46c1-45a4-81f9-ede0203ab266","trace_id":"627196cf-0a09-465a-ab3e-10e546adfcde"}
[2026-05-28 08:10:44] local.INFO: $params
Array
(
[historyTypes] => messageAdded
[startHistoryId] => 359025
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
[2026-05-28 08:10:44] local.INFO: $messageHistory
Array
(
)
{"correlation_id":"8667713e-79c8-46a6-b5a4-b13351d287da","trace_id":"52ec740a-b685-4b96-abda-8e5ab1057ea6"}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|