able to use resend for pro+ users
This commit is contained in:
		@@ -12,20 +12,21 @@ class ServerController extends Controller
 | 
			
		||||
 | 
			
		||||
    public function new_server()
 | 
			
		||||
    {
 | 
			
		||||
        $privateKeys = PrivateKey::ownedByCurrentTeam()->get();
 | 
			
		||||
        if (!isCloud()) {
 | 
			
		||||
            return view('server.create', [
 | 
			
		||||
                'limit_reached' => false,
 | 
			
		||||
                'private_keys' => PrivateKey::ownedByCurrentTeam()->get(),
 | 
			
		||||
                'private_keys' => $privateKeys,
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
        $servers = currentTeam()->servers->count();
 | 
			
		||||
        $subscription = currentTeam()?->subscription->type();
 | 
			
		||||
        $your_limit = config('constants.limits.server')[strtolower($subscription)];
 | 
			
		||||
        $limit_reached = $servers >= $your_limit;
 | 
			
		||||
        $team = currentTeam();
 | 
			
		||||
        $servers = $team->servers->count();
 | 
			
		||||
        ['serverLimit' => $serverLimit] = $team->limits;
 | 
			
		||||
        $limit_reached = $servers >= $serverLimit;
 | 
			
		||||
 | 
			
		||||
        return view('server.create', [
 | 
			
		||||
            'limit_reached' => $limit_reached,
 | 
			
		||||
            'private_keys' => PrivateKey::ownedByCurrentTeam()->get(),
 | 
			
		||||
            'private_keys' => $privateKeys,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ use App\Models\Project;
 | 
			
		||||
use App\Models\S3Storage;
 | 
			
		||||
use App\Models\Server;
 | 
			
		||||
use Livewire\Component;
 | 
			
		||||
use Log;
 | 
			
		||||
 | 
			
		||||
class Dashboard extends Component
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -6,55 +6,143 @@ use App\Models\InstanceSettings;
 | 
			
		||||
use App\Models\Team;
 | 
			
		||||
use App\Notifications\Test;
 | 
			
		||||
use Livewire\Component;
 | 
			
		||||
use Log;
 | 
			
		||||
 | 
			
		||||
class EmailSettings extends Component
 | 
			
		||||
{
 | 
			
		||||
    public Team $model;
 | 
			
		||||
    public Team $team;
 | 
			
		||||
    public string $emails;
 | 
			
		||||
    public bool $sharedEmailEnabled = false;
 | 
			
		||||
 | 
			
		||||
    protected $rules = [
 | 
			
		||||
        'model.smtp_enabled' => 'nullable|boolean',
 | 
			
		||||
        'model.smtp_from_address' => 'required|email',
 | 
			
		||||
        'model.smtp_from_name' => 'required',
 | 
			
		||||
        'model.smtp_recipients' => 'nullable',
 | 
			
		||||
        'model.smtp_host' => 'required',
 | 
			
		||||
        'model.smtp_port' => 'required',
 | 
			
		||||
        'model.smtp_encryption' => 'nullable',
 | 
			
		||||
        'model.smtp_username' => 'nullable',
 | 
			
		||||
        'model.smtp_password' => 'nullable',
 | 
			
		||||
        'model.smtp_timeout' => 'nullable',
 | 
			
		||||
        'model.smtp_notifications_test' => 'nullable|boolean',
 | 
			
		||||
        'model.smtp_notifications_deployments' => 'nullable|boolean',
 | 
			
		||||
        'model.smtp_notifications_status_changes' => 'nullable|boolean',
 | 
			
		||||
        'model.smtp_notifications_database_backups' => 'nullable|boolean',
 | 
			
		||||
        'team.smtp_enabled' => 'nullable|boolean',
 | 
			
		||||
        'team.smtp_from_address' => 'required|email',
 | 
			
		||||
        'team.smtp_from_name' => 'required',
 | 
			
		||||
        'team.smtp_recipients' => 'nullable',
 | 
			
		||||
        'team.smtp_host' => 'required',
 | 
			
		||||
        'team.smtp_port' => 'required',
 | 
			
		||||
        'team.smtp_encryption' => 'nullable',
 | 
			
		||||
        'team.smtp_username' => 'nullable',
 | 
			
		||||
        'team.smtp_password' => 'nullable',
 | 
			
		||||
        'team.smtp_timeout' => 'nullable',
 | 
			
		||||
        'team.smtp_notifications_test' => 'nullable|boolean',
 | 
			
		||||
        'team.smtp_notifications_deployments' => 'nullable|boolean',
 | 
			
		||||
        'team.smtp_notifications_status_changes' => 'nullable|boolean',
 | 
			
		||||
        'team.smtp_notifications_database_backups' => 'nullable|boolean',
 | 
			
		||||
        'team.use_instance_email_settings' => 'boolean',
 | 
			
		||||
        'team.resend_enabled' => 'nullable|boolean',
 | 
			
		||||
        'team.resend_api_key' => 'nullable',
 | 
			
		||||
    ];
 | 
			
		||||
    protected $validationAttributes = [
 | 
			
		||||
        'model.smtp_from_address' => 'From Address',
 | 
			
		||||
        'model.smtp_from_name' => 'From Name',
 | 
			
		||||
        'model.smtp_recipients' => 'Recipients',
 | 
			
		||||
        'model.smtp_host' => 'Host',
 | 
			
		||||
        'model.smtp_port' => 'Port',
 | 
			
		||||
        'model.smtp_encryption' => 'Encryption',
 | 
			
		||||
        'model.smtp_username' => 'Username',
 | 
			
		||||
        'model.smtp_password' => 'Password',
 | 
			
		||||
        'team.smtp_from_address' => 'From Address',
 | 
			
		||||
        'team.smtp_from_name' => 'From Name',
 | 
			
		||||
        'team.smtp_recipients' => 'Recipients',
 | 
			
		||||
        'team.smtp_host' => 'Host',
 | 
			
		||||
        'team.smtp_port' => 'Port',
 | 
			
		||||
        'team.smtp_encryption' => 'Encryption',
 | 
			
		||||
        'team.smtp_username' => 'Username',
 | 
			
		||||
        'team.smtp_password' => 'Password',
 | 
			
		||||
        'team.smtp_timeout' => 'Timeout',
 | 
			
		||||
        'team.resend_enabled' => 'Resend Enabled',
 | 
			
		||||
        'team.resend_api_key' => 'Resend API Key',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public function mount()
 | 
			
		||||
    {
 | 
			
		||||
        $this->decrypt();
 | 
			
		||||
        ['sharedEmailEnabled' => $this->sharedEmailEnabled] = $this->team->limits;
 | 
			
		||||
        $this->emails = auth()->user()->email;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function decrypt()
 | 
			
		||||
    public function submitFromFields()
 | 
			
		||||
    {
 | 
			
		||||
        if (data_get($this->model, 'smtp_password')) {
 | 
			
		||||
        try {
 | 
			
		||||
                $this->model->smtp_password = decrypt($this->model->smtp_password);
 | 
			
		||||
            $this->resetErrorBag();
 | 
			
		||||
            $this->validate([
 | 
			
		||||
                'team.smtp_from_address' => 'required|email',
 | 
			
		||||
                'team.smtp_from_name' => 'required',
 | 
			
		||||
            ]);
 | 
			
		||||
            $this->team->save();
 | 
			
		||||
            $this->emit('success', 'Settings saved successfully.');
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function sendTestNotification()
 | 
			
		||||
    {
 | 
			
		||||
        $this->team->notify(new Test($this->emails));
 | 
			
		||||
        $this->emit('success', 'Test Email sent successfully.');
 | 
			
		||||
    }
 | 
			
		||||
    public function instantSaveInstance()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            if (!$this->sharedEmailEnabled) {
 | 
			
		||||
                throw new \Exception('Not allowed to change settings. Please upgrade your subscription.');
 | 
			
		||||
            }
 | 
			
		||||
            $this->team->smtp_enabled = false;
 | 
			
		||||
            $this->team->resend_enabled = false;
 | 
			
		||||
            $this->team->save();
 | 
			
		||||
            $this->emit('success', 'Settings saved successfully.');
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function instantSaveResend()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->team->smtp_enabled = false;
 | 
			
		||||
            $this->submitResend();
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            $this->team->smtp_enabled = false;
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function instantSave()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->team->resend_enabled = false;
 | 
			
		||||
            $this->submit();
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            $this->team->smtp_enabled = false;
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function submit()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->resetErrorBag();
 | 
			
		||||
            $this->validate([
 | 
			
		||||
                'team.smtp_from_address' => 'required|email',
 | 
			
		||||
                'team.smtp_from_name' => 'required',
 | 
			
		||||
                'team.smtp_host' => 'required',
 | 
			
		||||
                'team.smtp_port' => 'required|numeric',
 | 
			
		||||
                'team.smtp_encryption' => 'nullable',
 | 
			
		||||
                'team.smtp_username' => 'nullable',
 | 
			
		||||
                'team.smtp_password' => 'nullable',
 | 
			
		||||
                'team.smtp_timeout' => 'nullable',
 | 
			
		||||
            ]);
 | 
			
		||||
            $this->team->save();
 | 
			
		||||
            $this->emit('success', 'Settings saved successfully.');
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            $this->team->smtp_enabled = false;
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function submitResend()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->resetErrorBag();
 | 
			
		||||
            $this->validate([
 | 
			
		||||
                'team.resend_api_key' => 'required'
 | 
			
		||||
            ]);
 | 
			
		||||
            $this->team->save();
 | 
			
		||||
            refreshSession();
 | 
			
		||||
            $this->emit('success', 'Settings saved successfully.');
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            $this->team->resend_enabled = false;
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function copyFromInstanceSettings()
 | 
			
		||||
    {
 | 
			
		||||
        $settings = InstanceSettings::get();
 | 
			
		||||
@@ -72,55 +160,22 @@ class EmailSettings extends Component
 | 
			
		||||
                'smtp_password' => $settings->smtp_password,
 | 
			
		||||
                'smtp_timeout' => $settings->smtp_timeout,
 | 
			
		||||
            ]);
 | 
			
		||||
            $this->decrypt();
 | 
			
		||||
            if (is_a($team, Team::class)) {
 | 
			
		||||
            refreshSession();
 | 
			
		||||
            }
 | 
			
		||||
            $this->model = $team;
 | 
			
		||||
            $this->team = $team;
 | 
			
		||||
            $this->emit('success', 'Settings saved.');
 | 
			
		||||
        } else {
 | 
			
		||||
            $this->emit('error', 'Instance SMTP settings are not enabled.');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function sendTestNotification()
 | 
			
		||||
    {
 | 
			
		||||
        $this->model->notify(new Test($this->emails));
 | 
			
		||||
        $this->emit('success', 'Test Email sent successfully.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function instantSave()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->submit();
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            $this->model->smtp_enabled = false;
 | 
			
		||||
            $this->validate();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function submit()
 | 
			
		||||
    {
 | 
			
		||||
        $this->resetErrorBag();
 | 
			
		||||
        $this->validate();
 | 
			
		||||
 | 
			
		||||
        if ($this->model->smtp_password) {
 | 
			
		||||
            $this->model->smtp_password = encrypt($this->model->smtp_password);
 | 
			
		||||
        } else {
 | 
			
		||||
            $this->model->smtp_password = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->model->smtp_recipients = str_replace(' ', '', $this->model->smtp_recipients);
 | 
			
		||||
        $this->saveModel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function saveModel()
 | 
			
		||||
    {
 | 
			
		||||
        $this->model->save();
 | 
			
		||||
        $this->decrypt();
 | 
			
		||||
        if (is_a($this->model, Team::class)) {
 | 
			
		||||
        if ($settings->resend_enabled) {
 | 
			
		||||
            $team = currentTeam();
 | 
			
		||||
            $team->update([
 | 
			
		||||
                'resend_enabled' => $settings->resend_enabled,
 | 
			
		||||
                'resend_api_key' => $settings->resend_api_key,
 | 
			
		||||
            ]);
 | 
			
		||||
            refreshSession();
 | 
			
		||||
        }
 | 
			
		||||
            $this->team = $team;
 | 
			
		||||
            $this->emit('success', 'Settings saved.');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        $this->emit('error', 'Instance SMTP/Resend settings are not enabled.');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -54,14 +54,6 @@ class Email extends Component
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function instantSaveResend()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->submitResend();
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function submitResend() {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->resetErrorBag();
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ class Invitations extends Component
 | 
			
		||||
    {
 | 
			
		||||
        TeamInvitation::find($invitation_id)->delete();
 | 
			
		||||
        $this->refreshInvitations();
 | 
			
		||||
        $this->emit('success', 'Invitation revoked.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function refreshInvitations()
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ namespace App\Models;
 | 
			
		||||
 | 
			
		||||
use App\Notifications\Channels\SendsDiscord;
 | 
			
		||||
use App\Notifications\Channels\SendsEmail;
 | 
			
		||||
use Illuminate\Database\Eloquent\Casts\Attribute;
 | 
			
		||||
use Illuminate\Database\Eloquent\Model;
 | 
			
		||||
use Illuminate\Notifications\Notifiable;
 | 
			
		||||
 | 
			
		||||
@@ -14,6 +15,8 @@ class Team extends Model implements SendsDiscord, SendsEmail
 | 
			
		||||
    protected $guarded = [];
 | 
			
		||||
    protected $casts = [
 | 
			
		||||
        'personal_team' => 'boolean',
 | 
			
		||||
        'smtp_password' => 'encrypted',
 | 
			
		||||
        'resend_api_key' => 'encrypted',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public function routeNotificationForDiscord()
 | 
			
		||||
@@ -30,6 +33,27 @@ class Team extends Model implements SendsDiscord, SendsEmail
 | 
			
		||||
        }
 | 
			
		||||
        return explode(',', $recipients);
 | 
			
		||||
    }
 | 
			
		||||
    public function limits(): Attribute
 | 
			
		||||
    {
 | 
			
		||||
        return Attribute::make(
 | 
			
		||||
            get: function () {
 | 
			
		||||
                if (config('coolify.self_hosted') || $this->id === 0) {
 | 
			
		||||
                    $subscription = 'self-hosted';
 | 
			
		||||
                } else {
 | 
			
		||||
                    $subscription = data_get($this, 'subscription');
 | 
			
		||||
                    if (is_null($subscription)) {
 | 
			
		||||
                        $subscription = 'zero';
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $subscription = $subscription->type();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                $serverLimit = config('constants.limits.server')[strtolower($subscription)];
 | 
			
		||||
                $sharedEmailEnabled = config('constants.limits.email')[strtolower($subscription)];
 | 
			
		||||
                return ['serverLimit' => $serverLimit, 'sharedEmailEnabled' => $sharedEmailEnabled];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function members()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ class DeploymentFailed extends Notification implements ShouldQueue
 | 
			
		||||
    public function via(object $notifiable): array
 | 
			
		||||
    {
 | 
			
		||||
        $channels = [];
 | 
			
		||||
        $isEmailEnabled = data_get($notifiable, 'smtp_enabled');
 | 
			
		||||
        $isEmailEnabled = isEmailEnabled($notifiable);
 | 
			
		||||
        $isDiscordEnabled = data_get($notifiable, 'discord_enabled');
 | 
			
		||||
        $isSubscribedToEmailEvent = data_get($notifiable, 'smtp_notifications_deployments');
 | 
			
		||||
        $isSubscribedToDiscordEvent = data_get($notifiable, 'discord_notifications_deployments');
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ class EmailChannel
 | 
			
		||||
 | 
			
		||||
        $mailMessage = $notification->toMail($notifiable);
 | 
			
		||||
        if ($this->isResend) {
 | 
			
		||||
            foreach($recepients as $receipient) {
 | 
			
		||||
            foreach ($recepients as $receipient) {
 | 
			
		||||
                Mail::send(
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
@@ -35,7 +35,6 @@ class EmailChannel
 | 
			
		||||
                        ->html((string)$mailMessage->render())
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            Mail::send(
 | 
			
		||||
                [],
 | 
			
		||||
@@ -50,22 +49,26 @@ class EmailChannel
 | 
			
		||||
                    ->html((string)$mailMessage->render())
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function bootConfigs($notifiable): void
 | 
			
		||||
    {
 | 
			
		||||
        if (data_get($notifiable, 'use_instance_email_settings')) {
 | 
			
		||||
            $type = set_transanctional_email_settings();
 | 
			
		||||
            if (!$type) {
 | 
			
		||||
                throw new Exception('No email settings found.');
 | 
			
		||||
            }
 | 
			
		||||
            if ($type === 'resend') {
 | 
			
		||||
                $this->isResend = true;
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (data_get($notifiable, 'resend_enabled')) {
 | 
			
		||||
            $resendAPIKey = data_get($notifiable, 'resend_api_key');
 | 
			
		||||
            if ($resendAPIKey) {
 | 
			
		||||
            $this->isResend = true;
 | 
			
		||||
            config()->set('mail.default', 'resend');
 | 
			
		||||
                config()->set('resend.api_key', $resendAPIKey);
 | 
			
		||||
            }
 | 
			
		||||
            config()->set('resend.api_key', data_get($notifiable, 'resend_api_key'));
 | 
			
		||||
        }
 | 
			
		||||
        if (data_get($notifiable, 'smtp_enabled')) {
 | 
			
		||||
            $password = data_get($notifiable, 'smtp_password');
 | 
			
		||||
            if ($password) $password = decrypt($password);
 | 
			
		||||
            config()->set('mail.default', 'smtp');
 | 
			
		||||
            config()->set('mail.mailers.smtp', [
 | 
			
		||||
                "transport" => "smtp",
 | 
			
		||||
@@ -73,7 +76,7 @@ class EmailChannel
 | 
			
		||||
                "port" => data_get($notifiable, 'smtp_port'),
 | 
			
		||||
                "encryption" => data_get($notifiable, 'smtp_encryption'),
 | 
			
		||||
                "username" => data_get($notifiable, 'smtp_username'),
 | 
			
		||||
                "password" => $password,
 | 
			
		||||
                "password" => data_get($notifiable, 'smtp_password'),
 | 
			
		||||
                "timeout" => data_get($notifiable, 'smtp_timeout'),
 | 
			
		||||
                "local_domain" => null,
 | 
			
		||||
            ]);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,16 +4,20 @@ namespace App\Notifications\Channels;
 | 
			
		||||
 | 
			
		||||
use App\Models\InstanceSettings;
 | 
			
		||||
use App\Models\User;
 | 
			
		||||
use Exception;
 | 
			
		||||
use Illuminate\Mail\Message;
 | 
			
		||||
use Illuminate\Notifications\Notification;
 | 
			
		||||
use Illuminate\Support\Facades\Mail;
 | 
			
		||||
use Log;
 | 
			
		||||
 | 
			
		||||
class TransactionalEmailChannel
 | 
			
		||||
{
 | 
			
		||||
    private bool $isResend = false;
 | 
			
		||||
    public function send(User $notifiable, Notification $notification): void
 | 
			
		||||
    {
 | 
			
		||||
        $settings = InstanceSettings::get();
 | 
			
		||||
        if (data_get($settings, 'smtp_enabled') !== true) {
 | 
			
		||||
        if (!data_get($settings, 'smtp_enabled') && !data_get($settings, 'resend_enabled')) {
 | 
			
		||||
            Log::info('SMTP/Resend not enabled');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        $email = $notifiable->email;
 | 
			
		||||
@@ -22,22 +26,43 @@ class TransactionalEmailChannel
 | 
			
		||||
        }
 | 
			
		||||
        $this->bootConfigs();
 | 
			
		||||
        $mailMessage = $notification->toMail($notifiable);
 | 
			
		||||
        if ($this->isResend) {
 | 
			
		||||
            Mail::send(
 | 
			
		||||
                [],
 | 
			
		||||
                [],
 | 
			
		||||
                fn (Message $message) => $message
 | 
			
		||||
                    ->from(
 | 
			
		||||
                        data_get($settings, 'smtp_from_address'),
 | 
			
		||||
                    data_get($settings, 'smtp_from_name')
 | 
			
		||||
                        data_get($settings, 'smtp_from_name'),
 | 
			
		||||
                    )
 | 
			
		||||
                    ->to($email)
 | 
			
		||||
                    ->subject($mailMessage->subject)
 | 
			
		||||
                    ->html((string)$mailMessage->render())
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            Mail::send(
 | 
			
		||||
                [],
 | 
			
		||||
                [],
 | 
			
		||||
                fn (Message $message) => $message
 | 
			
		||||
                    ->from(
 | 
			
		||||
                        data_get($settings, 'smtp_from_address'),
 | 
			
		||||
                        data_get($settings, 'smtp_from_name'),
 | 
			
		||||
                    )
 | 
			
		||||
                    ->bcc($email)
 | 
			
		||||
                    ->subject($mailMessage->subject)
 | 
			
		||||
                    ->html((string)$mailMessage->render())
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function bootConfigs(): void
 | 
			
		||||
    {
 | 
			
		||||
        set_transanctional_email_settings();
 | 
			
		||||
        $type = set_transanctional_email_settings();
 | 
			
		||||
        if (!$type) {
 | 
			
		||||
            throw new Exception('No email settings found.');
 | 
			
		||||
        }
 | 
			
		||||
        if ($type === 'resend') {
 | 
			
		||||
            $this->isResend = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class BackupFailed extends Notification implements ShouldQueue
 | 
			
		||||
    public function via(object $notifiable): array
 | 
			
		||||
    {
 | 
			
		||||
        $channels = [];
 | 
			
		||||
        $isEmailEnabled = data_get($notifiable, 'smtp_enabled');
 | 
			
		||||
        $isEmailEnabled = isEmailEnabled($notifiable);
 | 
			
		||||
        $isDiscordEnabled = data_get($notifiable, 'discord_enabled');
 | 
			
		||||
        $isSubscribedToEmailEvent = data_get($notifiable, 'smtp_notifications_database_backups');
 | 
			
		||||
        $isSubscribedToDiscordEvent = data_get($notifiable, 'discord_notifications_database_backups');
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class BackupSuccess extends Notification implements ShouldQueue
 | 
			
		||||
    public function via(object $notifiable): array
 | 
			
		||||
    {
 | 
			
		||||
        $channels = [];
 | 
			
		||||
        $isEmailEnabled = data_get($notifiable, 'smtp_enabled');
 | 
			
		||||
        $isEmailEnabled = isEmailEnabled($notifiable);
 | 
			
		||||
        $isDiscordEnabled = data_get($notifiable, 'discord_enabled');
 | 
			
		||||
        $isSubscribedToEmailEvent = data_get($notifiable, 'smtp_notifications_database_backups');
 | 
			
		||||
        $isSubscribedToDiscordEvent = data_get($notifiable, 'discord_notifications_database_backups');
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ class NotReachable extends Notification implements ShouldQueue
 | 
			
		||||
    public function via(object $notifiable): array
 | 
			
		||||
    {
 | 
			
		||||
        $channels = [];
 | 
			
		||||
        $isEmailEnabled = data_get($notifiable, 'smtp_enabled');
 | 
			
		||||
        $isEmailEnabled = isEmailEnabled($notifiable);
 | 
			
		||||
        $isDiscordEnabled = data_get($notifiable, 'discord_enabled');
 | 
			
		||||
        $isSubscribedToEmailEvent = data_get($notifiable, 'smtp_notifications_status_changes');
 | 
			
		||||
        $isSubscribedToDiscordEvent = data_get($notifiable, 'discord_notifications_status_changes');
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ class Test extends Notification implements ShouldQueue
 | 
			
		||||
    public function via(object $notifiable): array
 | 
			
		||||
    {
 | 
			
		||||
        $channels = [];
 | 
			
		||||
        $isEmailEnabled = data_get($notifiable, 'smtp_enabled');
 | 
			
		||||
        $isEmailEnabled = isEmailEnabled($notifiable);
 | 
			
		||||
        $isDiscordEnabled = data_get($notifiable, 'discord_enabled');
 | 
			
		||||
 | 
			
		||||
        if ($isDiscordEnabled && empty($this->emails)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -31,24 +31,11 @@ class ResetPassword extends Notification
 | 
			
		||||
 | 
			
		||||
    public function via($notifiable)
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->settings->smtp_enabled) {
 | 
			
		||||
            $password = data_get($this->settings, 'smtp_password');
 | 
			
		||||
            if ($password) $password = decrypt($password);
 | 
			
		||||
 | 
			
		||||
            config()->set('mail.default', 'smtp');
 | 
			
		||||
            config()->set('mail.mailers.smtp', [
 | 
			
		||||
                "transport" => "smtp",
 | 
			
		||||
                "host" => data_get($this->settings, 'smtp_host'),
 | 
			
		||||
                "port" => data_get($this->settings, 'smtp_port'),
 | 
			
		||||
                "encryption" => data_get($this->settings, 'smtp_encryption'),
 | 
			
		||||
                "username" => data_get($this->settings, 'smtp_username'),
 | 
			
		||||
                "password" => $password,
 | 
			
		||||
                "timeout" => data_get($this->settings, 'smtp_timeout'),
 | 
			
		||||
                "local_domain" => null,
 | 
			
		||||
            ]);
 | 
			
		||||
            return ['mail'];
 | 
			
		||||
        $type = set_transanctional_email_settings();
 | 
			
		||||
        if (!$type) {
 | 
			
		||||
            throw new \Exception('No email settings found.');
 | 
			
		||||
        }
 | 
			
		||||
        throw new \Exception('SMTP is not enabled');
 | 
			
		||||
        return ['mail'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function toMail($notifiable)
 | 
			
		||||
 
 | 
			
		||||
@@ -122,10 +122,11 @@ function generateSSHKey()
 | 
			
		||||
    $key = RSA::createKey();
 | 
			
		||||
    return [
 | 
			
		||||
        'private' => $key->toString('PKCS1'),
 | 
			
		||||
        'public' => $key->getPublicKey()->toString('OpenSSH',['comment' => 'coolify-generated-ssh-key'])
 | 
			
		||||
        'public' => $key->getPublicKey()->toString('OpenSSH', ['comment' => 'coolify-generated-ssh-key'])
 | 
			
		||||
    ];
 | 
			
		||||
}
 | 
			
		||||
function formatPrivateKey(string $privateKey) {
 | 
			
		||||
function formatPrivateKey(string $privateKey)
 | 
			
		||||
{
 | 
			
		||||
    $privateKey = trim($privateKey);
 | 
			
		||||
    if (!str_ends_with($privateKey, "\n")) {
 | 
			
		||||
        $privateKey .= "\n";
 | 
			
		||||
@@ -140,19 +141,20 @@ function generate_application_name(string $git_repository, string $git_branch):
 | 
			
		||||
 | 
			
		||||
function is_transactional_emails_active(): bool
 | 
			
		||||
{
 | 
			
		||||
    return data_get(InstanceSettings::get(), 'smtp_enabled');
 | 
			
		||||
    return isEmailEnabled(InstanceSettings::get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function set_transanctional_email_settings(InstanceSettings | null $settings = null): void
 | 
			
		||||
function set_transanctional_email_settings(InstanceSettings | null $settings = null): string|null
 | 
			
		||||
{
 | 
			
		||||
    if (!$settings) {
 | 
			
		||||
        $settings = InstanceSettings::get();
 | 
			
		||||
    }
 | 
			
		||||
    $password = data_get($settings, 'smtp_password');
 | 
			
		||||
    if (isset($password)) {
 | 
			
		||||
        $password = decrypt($password);
 | 
			
		||||
    if (data_get($settings, 'resend_enabled')) {
 | 
			
		||||
        config()->set('mail.default', 'resend');
 | 
			
		||||
        config()->set('resend.api_key', data_get($settings, 'resend_api_key'));
 | 
			
		||||
        return 'resend';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (data_get($settings, 'smtp_enabled')) {
 | 
			
		||||
        config()->set('mail.default', 'smtp');
 | 
			
		||||
        config()->set('mail.mailers.smtp', [
 | 
			
		||||
            "transport" => "smtp",
 | 
			
		||||
@@ -160,10 +162,13 @@ function set_transanctional_email_settings(InstanceSettings | null $settings = n
 | 
			
		||||
            "port" => data_get($settings, 'smtp_port'),
 | 
			
		||||
            "encryption" => data_get($settings, 'smtp_encryption'),
 | 
			
		||||
            "username" => data_get($settings, 'smtp_username'),
 | 
			
		||||
        "password" => $password,
 | 
			
		||||
            "password" => data_get($settings, 'smtp_password'),
 | 
			
		||||
            "timeout" => data_get($settings, 'smtp_timeout'),
 | 
			
		||||
            "local_domain" => null,
 | 
			
		||||
        ]);
 | 
			
		||||
        return 'smtp';
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function base_ip(): string
 | 
			
		||||
@@ -246,7 +251,10 @@ function send_internal_notification(string $message): void
 | 
			
		||||
function send_user_an_email(MailMessage $mail, string $email): void
 | 
			
		||||
{
 | 
			
		||||
    $settings = InstanceSettings::get();
 | 
			
		||||
    set_transanctional_email_settings($settings);
 | 
			
		||||
    $type = set_transanctional_email_settings($settings);
 | 
			
		||||
    if (!$type) {
 | 
			
		||||
        throw new Exception('No email settings found.');
 | 
			
		||||
    }
 | 
			
		||||
    Mail::send(
 | 
			
		||||
        [],
 | 
			
		||||
        [],
 | 
			
		||||
@@ -259,5 +267,9 @@ function send_user_an_email(MailMessage $mail, string $email): void
 | 
			
		||||
            ->subject($mail->subject)
 | 
			
		||||
            ->html((string) $mail->render())
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
function isEmailEnabled($notifiable)
 | 
			
		||||
{
 | 
			
		||||
    return data_get($notifiable, 'smtp_enabled') || data_get($notifiable, 'resend_enabled') || data_get($notifiable, 'use_instance_email_settings');
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,6 @@ function isSubscriptionActive()
 | 
			
		||||
        return $subscription->stripe_invoice_paid === true && $subscription->stripe_cancel_at_period_end === false;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
function isSubscriptionOnGracePeriod()
 | 
			
		||||
{
 | 
			
		||||
@@ -92,13 +91,16 @@ function subscriptionProvider()
 | 
			
		||||
{
 | 
			
		||||
    return config('subscription.provider');
 | 
			
		||||
}
 | 
			
		||||
function isLemon () {
 | 
			
		||||
function isLemon()
 | 
			
		||||
{
 | 
			
		||||
    return config('subscription.provider') === 'lemon';
 | 
			
		||||
}
 | 
			
		||||
function isStripe() {
 | 
			
		||||
function isStripe()
 | 
			
		||||
{
 | 
			
		||||
    return config('subscription.provider') === 'stripe';
 | 
			
		||||
}
 | 
			
		||||
function isPaddle() {
 | 
			
		||||
function isPaddle()
 | 
			
		||||
{
 | 
			
		||||
    return config('subscription.provider') === 'paddle';
 | 
			
		||||
}
 | 
			
		||||
function getStripeCustomerPortalSession(Team $team)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,11 +11,15 @@ return [
 | 
			
		||||
    ],
 | 
			
		||||
    'limits' => [
 | 
			
		||||
        'server' => [
 | 
			
		||||
            'zero' => 0,
 | 
			
		||||
            'self-hosted' => 999999999999,
 | 
			
		||||
            'basic' => 1,
 | 
			
		||||
            'pro' => 10,
 | 
			
		||||
            'ultimate' => 25,
 | 
			
		||||
        ],
 | 
			
		||||
        'smtp' => [
 | 
			
		||||
        'email' => [
 | 
			
		||||
            'zero' => false,
 | 
			
		||||
            'self-hosted' => true,
 | 
			
		||||
            'basic' => false,
 | 
			
		||||
            'pro' => true,
 | 
			
		||||
            'ultimate' => true,
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Migrations\Migration;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
 | 
			
		||||
return new class extends Migration
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the migrations.
 | 
			
		||||
     */
 | 
			
		||||
    public function up(): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::table('teams', function (Blueprint $table) {
 | 
			
		||||
            $table->boolean('resend_enabled')->default(false);
 | 
			
		||||
            $table->text('resend_api_key')->nullable();
 | 
			
		||||
            $table->boolean('use_instance_email_settings')->default(false);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     */
 | 
			
		||||
    public function down(): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::table('teams', function (Blueprint $table) {
 | 
			
		||||
            $table->dropColumn('resend_enabled');
 | 
			
		||||
            $table->dropColumn('resend_api_key');
 | 
			
		||||
            $table->dropColumn('use_instance_email_settings');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,14 +1,13 @@
 | 
			
		||||
Congratulations!<br>
 | 
			
		||||
Congratulations!<br>
 | 
			
		||||
<br>
 | 
			
		||||
You have been invited to join the Coolify Cloud. <a href="{{base_url()}}/login">Login here</a>
 | 
			
		||||
<br>
 | 
			
		||||
<br>
 | 
			
		||||
Credentials:
 | 
			
		||||
<br>
 | 
			
		||||
Email: {{ $email }}
 | 
			
		||||
<br>
 | 
			
		||||
Password: {{ $password }}
 | 
			
		||||
Here is your initial login information.
 | 
			
		||||
<br>
 | 
			
		||||
Email: <br>
 | 
			
		||||
{{ $email }}
 | 
			
		||||
<br><br>
 | 
			
		||||
Password:<br>
 | 
			
		||||
{{ $password }}
 | 
			
		||||
<br><br>
 | 
			
		||||
(You will forced to change it on first login.)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@
 | 
			
		||||
 | 
			
		||||
                function copyToClipboard(text) {
 | 
			
		||||
                    navigator.clipboard.writeText(text);
 | 
			
		||||
                    Livewire.emit('message', 'Copied to clipboard.');
 | 
			
		||||
                    Livewire.emit('success', 'Copied to clipboard.');
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Livewire.on('reloadWindow', (timeout) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,59 +16,106 @@
 | 
			
		||||
            <x-forms.button type="submit">
 | 
			
		||||
                Save
 | 
			
		||||
            </x-forms.button>
 | 
			
		||||
            @if (isInstanceAdmin())
 | 
			
		||||
            @if (isInstanceAdmin() && !$team->use_instance_email_settings)
 | 
			
		||||
                <x-forms.button wire:click='copyFromInstanceSettings'>
 | 
			
		||||
                    Copy from Instance Settings
 | 
			
		||||
                </x-forms.button>
 | 
			
		||||
            @endif
 | 
			
		||||
            @if ($model->smtp_enabled)
 | 
			
		||||
            @if (isEmailEnabled($team) || data_get($team, 'use_instance_email_settings'))
 | 
			
		||||
                <x-forms.button onclick="sendTestEmail.showModal()"
 | 
			
		||||
                    class="text-white normal-case btn btn-xs no-animation btn-primary">
 | 
			
		||||
                    Send Test Email
 | 
			
		||||
                </x-forms.button>
 | 
			
		||||
            @endif
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="w-48">
 | 
			
		||||
            <x-forms.checkbox instantSave id="model.smtp_enabled" label="Notification Enabled" />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="flex flex-col gap-4">
 | 
			
		||||
            <div class="flex flex-col gap-2 xl:flex-row">
 | 
			
		||||
                <x-forms.input id="model.smtp_recipients"
 | 
			
		||||
                    placeholder="If empty, all users will be notified in the team."
 | 
			
		||||
                    helper="Email list to send the all notifications to, separated by comma." label="Recipients" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex flex-col gap-2 xl:flex-row">
 | 
			
		||||
                <x-forms.input required id="model.smtp_host" helper="SMTP Hostname" placeholder="smtp.mailgun.org"
 | 
			
		||||
                    label="Host" />
 | 
			
		||||
                <x-forms.input required id="model.smtp_port" helper="SMTP Port" placeholder="587" label="Port" />
 | 
			
		||||
                <x-forms.input helper="If SMTP through SSL, set it to 'tls'." placeholder="tls"
 | 
			
		||||
                    id="model.smtp_encryption" label="Encryption" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex flex-col gap-2 xl:flex-row">
 | 
			
		||||
                <x-forms.input id="model.smtp_username" label="SMTP Username" />
 | 
			
		||||
                <x-forms.input type="password" id="model.smtp_password" label="SMTP Password" />
 | 
			
		||||
                <x-forms.input id="model.smtp_timeout" helper="Timeout value for sending emails." label="Timeout" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex flex-col gap-2 xl:flex-row">
 | 
			
		||||
                <x-forms.input required id="model.smtp_from_name" helper="Name used in emails." label="From Name" />
 | 
			
		||||
                <x-forms.input required id="model.smtp_from_address" helper="Email address used in emails."
 | 
			
		||||
                    label="From Address" />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    </form>
 | 
			
		||||
    @if (data_get($model, 'smtp_enabled'))
 | 
			
		||||
        <h4 class="mt-4">Subscribe to events</h4>
 | 
			
		||||
    @if ($this->sharedEmailEnabled)
 | 
			
		||||
        <div class="w-64 pb-4">
 | 
			
		||||
            <x-forms.checkbox instantSave="instantSaveInstance" id="team.use_instance_email_settings"
 | 
			
		||||
                label="Use hosted email service" />
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if (!$team->use_instance_email_settings)
 | 
			
		||||
        <form class="flex flex-col items-end gap-2 pb-4 xl:flex-row" wire:submit.prevent='submitFromFields'>
 | 
			
		||||
            <x-forms.input required id="team.smtp_from_name" helper="Name used in emails." label="From Name" />
 | 
			
		||||
            <x-forms.input required id="team.smtp_from_address" helper="Email address used in emails."
 | 
			
		||||
                label="From Address" />
 | 
			
		||||
            <x-forms.button type="submit">
 | 
			
		||||
                Save
 | 
			
		||||
            </x-forms.button>
 | 
			
		||||
        </form>
 | 
			
		||||
        <div class="flex flex-col gap-4">
 | 
			
		||||
            <details class="border rounded collapse border-coolgray-500 collapse-arrow ">
 | 
			
		||||
                <summary class="text-xl collapse-title">
 | 
			
		||||
                    <div>SMTP Server</div>
 | 
			
		||||
                    <div class="w-32">
 | 
			
		||||
                        <x-forms.checkbox instantSave id="team.smtp_enabled" label="Enabled" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </summary>
 | 
			
		||||
                <div class="collapse-content">
 | 
			
		||||
                    <form wire:submit.prevent='submit' class="flex flex-col">
 | 
			
		||||
                        <div class="flex flex-col gap-4">
 | 
			
		||||
                            <div class="flex flex-col w-full gap-2 xl:flex-row">
 | 
			
		||||
                                <x-forms.input required id="team.smtp_host" placeholder="smtp.mailgun.org"
 | 
			
		||||
                                    label="Host" />
 | 
			
		||||
                                <x-forms.input required id="team.smtp_port" placeholder="587" label="Port" />
 | 
			
		||||
                                <x-forms.input id="team.smtp_encryption" helper="If SMTP uses SSL, set it to 'tls'."
 | 
			
		||||
                                    placeholder="tls" label="Encryption" />
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="flex flex-col w-full gap-2 xl:flex-row">
 | 
			
		||||
                                <x-forms.input id="team.smtp_username" label="SMTP Username" />
 | 
			
		||||
                                <x-forms.input id="team.smtp_password" type="password" label="SMTP Password" />
 | 
			
		||||
                                <x-forms.input id="team.smtp_timeout" helper="Timeout value for sending emails."
 | 
			
		||||
                                    label="Timeout" />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="flex justify-end gap-4 pt-6">
 | 
			
		||||
                            <x-forms.button type="submit">
 | 
			
		||||
                                Save
 | 
			
		||||
                            </x-forms.button>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </form>
 | 
			
		||||
                </div>
 | 
			
		||||
            </details>
 | 
			
		||||
            <details class="border rounded collapse border-coolgray-500 collapse-arrow">
 | 
			
		||||
                <summary class="text-xl collapse-title">
 | 
			
		||||
                    <div>Resend</div>
 | 
			
		||||
                    <div class="w-32">
 | 
			
		||||
                        <x-forms.checkbox instantSave='instantSaveResend' id="team.resend_enabled" label="Enabled" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </summary>
 | 
			
		||||
                <div class="collapse-content">
 | 
			
		||||
                    <form wire:submit.prevent='submitResend' class="flex flex-col">
 | 
			
		||||
                        <div class="flex flex-col gap-4">
 | 
			
		||||
                            <div class="flex flex-col w-full gap-2 xl:flex-row">
 | 
			
		||||
                                <x-forms.input type="password" id="team.resend_api_key" placeholder="API key"
 | 
			
		||||
                                    label="Host" />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="flex justify-end gap-4 pt-6">
 | 
			
		||||
                            <x-forms.button type="submit">
 | 
			
		||||
                                Save
 | 
			
		||||
                            </x-forms.button>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </form>
 | 
			
		||||
                </div>
 | 
			
		||||
            </details>
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if (isEmailEnabled($team) || data_get($team, 'use_instance_email_settings'))
 | 
			
		||||
        <h3 class="mt-4">Subscribe to events</h3>
 | 
			
		||||
        <div class="w-64">
 | 
			
		||||
            @if (isDev())
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="model.smtp_notifications_test" label="Test" />
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_test" label="Test" />
 | 
			
		||||
            @endif
 | 
			
		||||
            <h4 class="mt-4">General</h4>
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="model.smtp_notifications_status_changes"
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_status_changes"
 | 
			
		||||
                label="Container Status Changes" />
 | 
			
		||||
            <h4 class="mt-4">Applications</h4>
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="model.smtp_notifications_deployments" label="Deployments" />
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_deployments" label="Deployments" />
 | 
			
		||||
            <h4 class="mt-4">Databases</h4>
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="model.smtp_notifications_database_backups"
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_database_backups"
 | 
			
		||||
                label="Backup Statuses" />
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,9 @@
 | 
			
		||||
        </form>
 | 
			
		||||
    </dialog>
 | 
			
		||||
    <div class="flex items-center gap-2">
 | 
			
		||||
        <h2>Transactional Emails</h2>
 | 
			
		||||
        <h2>Transactional/Shared Email</h2>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="pb-4 ">SMTP settings for password resets, invitations, etc.</div>
 | 
			
		||||
    <div class="pb-4 ">Email settings for password resets, invitations, shared with Pro+ subscribers etc.</div>
 | 
			
		||||
    <form wire:submit.prevent='submitFromFields' class="pb-4">
 | 
			
		||||
        <div class="flex flex-col items-end w-full gap-2 xl:flex-row">
 | 
			
		||||
            <x-forms.input required id="settings.smtp_from_name" helper="Name used in emails." label="From Name" />
 | 
			
		||||
@@ -63,11 +63,11 @@
 | 
			
		||||
                </form>
 | 
			
		||||
            </div>
 | 
			
		||||
        </details>
 | 
			
		||||
        <details class="border rounded collapse border-coolgray-500 collapse-arrow ">
 | 
			
		||||
        <details class="border rounded collapse border-coolgray-500 collapse-arrow">
 | 
			
		||||
            <summary class="text-xl collapse-title">
 | 
			
		||||
                <div>Resend</div>
 | 
			
		||||
                <div class="w-32">
 | 
			
		||||
                    <x-forms.checkbox instantSave='instantSaveResend' id="settings.resend_enabled" label="Enabled" />
 | 
			
		||||
                    <x-forms.checkbox instantSave='submitResend' id="settings.resend_enabled" label="Enabled" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <div class="collapse-content">
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,9 @@
 | 
			
		||||
            <a :class="activeTab === 'general' && 'text-white'"
 | 
			
		||||
                @click.prevent="activeTab = 'general'; window.location.hash = 'general'" href="#">General</a>
 | 
			
		||||
            <a :class="activeTab === 'backup' && 'text-white'"
 | 
			
		||||
                @click.prevent="activeTab = 'backup'; window.location.hash = 'backup'" href="#">Backup</a>
 | 
			
		||||
                @click.prevent="activeTab = 'backup'; window.location.hash = 'backup'" href="#">Instance Backup</a>
 | 
			
		||||
            <a :class="activeTab === 'smtp' && 'text-white'"
 | 
			
		||||
                @click.prevent="activeTab = 'smtp'; window.location.hash = 'smtp'" href="#">SMTP</a>
 | 
			
		||||
                @click.prevent="activeTab = 'smtp'; window.location.hash = 'smtp'" href="#">Transactional/Shared Email</a>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="w-full pl-8">
 | 
			
		||||
            <div x-cloak x-show="activeTab === 'general'" class="h-full">
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="w-full pl-8">
 | 
			
		||||
            <div x-cloak x-show="activeTab === 'email'" class="h-full">
 | 
			
		||||
                <livewire:notifications.email-settings :model="auth()
 | 
			
		||||
                <livewire:notifications.email-settings :team="auth()
 | 
			
		||||
                    ->user()
 | 
			
		||||
                    ->currentTeam()" />
 | 
			
		||||
            </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,10 @@ use Laravel\Fortify\Fortify;
 | 
			
		||||
 | 
			
		||||
Route::post('/forgot-password', function (Request $request) {
 | 
			
		||||
    if (is_transactional_emails_active()) {
 | 
			
		||||
        set_transanctional_email_settings();
 | 
			
		||||
        $type = set_transanctional_email_settings();
 | 
			
		||||
        if (!$type) {
 | 
			
		||||
            return response()->json(['message' => 'Transactional emails are not active'], 400);
 | 
			
		||||
        }
 | 
			
		||||
        $request->validate([Fortify::email() => 'required|email']);
 | 
			
		||||
        $status = Password::broker(config('fortify.passwords'))->sendResetLink(
 | 
			
		||||
            $request->only(Fortify::email())
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user