{"record":{"id":"13f03b0b9a68ee36","repo":"coollabsio/coolify","slug":"recipient-is-not-part-of-the-team","errorCode":null,"errorMessage":"Recipient is not part of the team","messagePattern":"Recipient is not part of the team","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"app/Notifications/Channels/EmailChannel.php","lineNumber":64,"sourceCode":"            // Skip team membership validation for test notifications\n            $isTestNotification = data_get($notification, 'isTestNotification', false);\n\n            if (! $isTestNotification) {\n                foreach ($recipients as $recipient) {\n                    // Check if the recipient is part of the team\n                    if (! $members->contains('email', $recipient)) {\n                        $emailSettings = $notifiable->emailNotificationSettings;\n                        data_set($emailSettings, 'smtp_password', '********');\n                        data_set($emailSettings, 'resend_api_key', '********');\n                        send_internal_notification(sprintf(\n                            \"Recipient is not part of the team: %s\\nTeam: %s\\nNotification: %s\\nNotifiable: %s\\nEmail Settings:\\n%s\",\n                            $recipient,\n                            $team,\n                            get_class($notification),\n                            get_class($notifiable),\n                            json_encode($emailSettings, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)\n                        ));\n                        throw new Exception('Recipient is not part of the team');\n                    }\n                }\n            }\n\n            $mailMessage = $notification->toMail($notifiable);\n\n            if ($isResendEnabled) {\n                $resend = Resend::client($settings->resend_api_key);\n                $from = \"{$settings->smtp_from_name} <{$settings->smtp_from_address}>\";\n                $resend->emails->send([\n                    'from' => $from,\n                    'to' => $recipients,\n                    'subject' => $mailMessage->subject,\n                    'html' => (string) $mailMessage->render(),\n                ]);\n            } elseif ($isSmtpEnabled) {\n                $encryption = match (strtolower($settings->smtp_encryption)) {\n                    'starttls' => null,","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/coollabsio/coolify/blob/70b9acc42467278373e00de77abb40684e25b395/app/Notifications/Channels/EmailChannel.php#L46-L82","documentation":"EmailChannel validates every resolved recipient against the team's member emails ($members->contains('email', $recipient)). A recipient not on that list — custom email of an outsider, a stale address, a case-mismatched duplicate — first triggers an internal notification (with masked SMTP/Resend secrets) and then throws, aborting the whole email send.","triggerScenarios":"Custom recipient typed with a typo or belonging to a non-member; team member changed their email but notification settings/custom recipients still hold the old one; mixed-case address not exactly matching the stored member email (comparison is exact).","commonSituations":"Sending deployment notifications to a client's address not on the team; member email rotation; uppercase variants of the same Gmail address.","solutions":["Use email addresses that exactly match current team members (check Members list).","Remove or update stale custom recipients after members change their email.","Match the address casing used on the member record.","To notify externals, invite them as team members first — Coolify enforces team membership by design."],"exampleFix":"// before: custom recipient outside the team\n$notification->setEmailRecipients('client@example.com');\n\n// after: only team member addresses\n$notification->setEmailRecipients($team->members()->pluck('email')->implode(','));","handlingStrategy":"validation","validationCode":"// Filter recipients to verified team member emails before sending\n$memberEmails = $team->members()->pluck('email')->map(fn ($e) => strtolower(trim($e)))->all();\n$recipients = array_values(array_filter($recipients, fn ($r) => in_array(strtolower(trim($r)), $memberEmails, true)));\nif ($recipients === []) { /* skip or warn instead of mid-send failure */ }","typeGuard":null,"tryCatchPattern":"catch (Exception $e) { if ($e->getMessage() === 'Recipient is not part of the team') { flag the notification's recipient list as stale in settings UI rather than crashing the send loop. } else { throw $e; } }","preventionTips":["Source custom recipients only from the member picker, never free text.","When members change their email, update notification recipients automatically.","Normalize casing/whitespace before comparing or storing emails."],"tags":["email","notifications","recipients","authorization","coolify"],"backgroundTag":"recipient-validation-failed","analyzedSha":"70b9acc42467278373e00de77abb40684e25b395","analyzedAt":"2026-08-17T01:41:01.313Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}