From 2538890b5276a601aad9ab5c8cebdd9e6374c72a Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 31 Aug 2023 13:10:39 +0200 Subject: [PATCH] feat: add resend as transactional emails --- app/Http/Livewire/Settings/Email.php | 77 +++++++++---- app/Models/InstanceSettings.php | 1 + app/Notifications/Channels/EmailChannel.php | 63 +++++++---- app/View/Components/Forms/Checkbox.php | 2 +- .../2023_08_22_071052_add_resend_as_email.php | 30 ++++++ .../views/livewire/settings/email.blade.php | 102 ++++++++++++------ 6 files changed, 200 insertions(+), 75 deletions(-) create mode 100644 database/migrations/2023_08_22_071052_add_resend_as_email.php diff --git a/app/Http/Livewire/Settings/Email.php b/app/Http/Livewire/Settings/Email.php index a0ac3c904..0256b6021 100644 --- a/app/Http/Livewire/Settings/Email.php +++ b/app/Http/Livewire/Settings/Email.php @@ -20,6 +20,9 @@ class Email extends Component 'settings.smtp_timeout' => 'nullable', 'settings.smtp_from_address' => 'required|email', 'settings.smtp_from_name' => 'required', + 'settings.resend_enabled' => 'nullable|boolean', + 'settings.resend_api_key' => 'nullable' + ]; protected $validationAttributes = [ 'settings.smtp_from_address' => 'From Address', @@ -30,48 +33,76 @@ class Email extends Component 'settings.smtp_encryption' => 'Encryption', 'settings.smtp_username' => 'Username', 'settings.smtp_password' => 'Password', + 'settings.smtp_timeout' => 'Timeout', + 'settings.resend_api_key' => 'Resend API Key' ]; - public function mount() { - $this->decrypt(); $this->emails = auth()->user()->email; } - private function decrypt() - { - if (data_get($this->settings, 'smtp_password')) { - try { - $this->settings->smtp_password = decrypt($this->settings->smtp_password); - } catch (\Exception $e) { - } + public function submitFromFields() { + try { + $this->resetErrorBag(); + $this->validate([ + 'settings.smtp_from_address' => 'required|email', + 'settings.smtp_from_name' => 'required', + ]); + $this->settings->save(); + $this->emit('success', 'Settings saved successfully.'); + } catch (\Exception $e) { + 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(); + $this->validate([ + 'settings.resend_api_key' => 'required' + ]); + $this->settings->smtp_enabled = false; + $this->settings->save(); + $this->emit('success', 'Settings saved successfully.'); + } catch (\Exception $e) { + $this->settings->resend_enabled = false; + return general_error_handler($e, $this); } } - public function instantSave() { try { $this->submit(); - $this->emit('success', 'Settings saved successfully.'); } catch (\Exception $e) { - $this->settings->smtp_enabled = false; - $this->validate(); + return general_error_handler($e, $this); } } public function submit() { - $this->resetErrorBag(); - $this->validate(); - if ($this->settings->smtp_password) { - $this->settings->smtp_password = encrypt($this->settings->smtp_password); - } else { - $this->settings->smtp_password = null; + try { + $this->resetErrorBag(); + $this->validate([ + 'settings.smtp_host' => 'required', + 'settings.smtp_port' => 'required|numeric', + 'settings.smtp_encryption' => 'nullable', + 'settings.smtp_username' => 'nullable', + 'settings.smtp_password' => 'nullable', + 'settings.smtp_timeout' => 'nullable', + ]); + $this->settings->resend_enabled = false; + $this->settings->save(); + $this->emit('success', 'Settings saved successfully.'); + } catch (\Exception $e) { + return general_error_handler($e, $this); } - - $this->settings->save(); - $this->emit('success', 'Transaction email settings updated successfully.'); - $this->decrypt(); } public function sendTestNotification() diff --git a/app/Models/InstanceSettings.php b/app/Models/InstanceSettings.php index 0fc892d92..057595351 100644 --- a/app/Models/InstanceSettings.php +++ b/app/Models/InstanceSettings.php @@ -13,6 +13,7 @@ class InstanceSettings extends Model implements SendsEmail protected $guarded = []; protected $casts = [ 'resale_license' => 'encrypted', + 'smtp_password' => 'encrypted', ]; public static function get() diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index b412bebd6..afb30d0c9 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -6,10 +6,10 @@ use Illuminate\Mail\Message; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Mail; -use Illuminate\Support\Str; class EmailChannel { + private bool $isResend = false; public function send(SendsEmail $notifiable, Notification $notification): void { $this->bootConfigs($notifiable); @@ -20,29 +20,52 @@ public function send(SendsEmail $notifiable, Notification $notification): void } $mailMessage = $notification->toMail($notifiable); - Mail::send( - [], - [], - fn (Message $message) => $message - ->from( - data_get($notifiable, 'smtp_from_address'), - data_get($notifiable, 'smtp_from_name'), - ) - ->bcc($recepients) - ->subject($mailMessage->subject) - ->html((string)$mailMessage->render()) - ); + if ($this->isResend) { + foreach($recepients as $receipient) { + Mail::send( + [], + [], + fn (Message $message) => $message + ->from( + data_get($notifiable, 'smtp_from_address'), + data_get($notifiable, 'smtp_from_name'), + ) + ->to($receipient) + ->subject($mailMessage->subject) + ->html((string)$mailMessage->render()) + ); + } + + } else { + Mail::send( + [], + [], + fn (Message $message) => $message + ->from( + data_get($notifiable, 'smtp_from_address'), + data_get($notifiable, 'smtp_from_name'), + ) + ->bcc($recepients) + ->subject($mailMessage->subject) + ->html((string)$mailMessage->render()) + ); + } + } private function bootConfigs($notifiable): void { - $password = data_get($notifiable, 'smtp_password'); - if ($password) $password = decrypt($password); - - if (Str::contains(data_get($notifiable, 'smtp_host'),'resend.com')) { - config()->set('mail.default', 'resend'); - config()->set('resend.api_key', $password); - } else { + 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); + } + } + 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", diff --git a/app/View/Components/Forms/Checkbox.php b/app/View/Components/Forms/Checkbox.php index 1f1d634f3..4fd05c2dd 100644 --- a/app/View/Components/Forms/Checkbox.php +++ b/app/View/Components/Forms/Checkbox.php @@ -17,7 +17,7 @@ public function __construct( public string|null $value = null, public string|null $label = null, public string|null $helper = null, - public bool $instantSave = false, + public string|bool $instantSave = false, public bool $disabled = false, public string $defaultClass = "toggle toggle-xs toggle-warning rounded disabled:bg-coolgray-200 disabled:opacity-50 placeholder:text-neutral-700" ) { diff --git a/database/migrations/2023_08_22_071052_add_resend_as_email.php b/database/migrations/2023_08_22_071052_add_resend_as_email.php new file mode 100644 index 000000000..fd7368bfe --- /dev/null +++ b/database/migrations/2023_08_22_071052_add_resend_as_email.php @@ -0,0 +1,30 @@ +boolean('resend_enabled')->default(false); + $table->text('resend_api_key')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('instance_settings', function (Blueprint $table) { + $table->dropColumn('resend_enabled'); + $table->dropColumn('resend_api_key'); + }); + } +}; diff --git a/resources/views/livewire/settings/email.blade.php b/resources/views/livewire/settings/email.blade.php index f528e6273..57f66c19f 100644 --- a/resources/views/livewire/settings/email.blade.php +++ b/resources/views/livewire/settings/email.blade.php @@ -10,40 +10,80 @@ -
-
-

Transactional Emails

+
+

Transactional Emails

+
+
SMTP settings for password resets, invitations, etc.
+ +
+ + Save - @if ($settings->smtp_enabled) - - Send Test Email - - @endif -
-
SMTP settings for password resets, invitations, etc.
-
- -
-
-
- - - -
-
- - - -
-
- - -
+ @if ($settings->resend_enabled || $settings->smtp_enabled) + + Send Test Email + + @endif
+
+
+ +
SMTP Server
+
+ +
+
+
+
+
+
+ + + +
+
+ + + +
+
+
+ + Save + +
+
+
+
+
+ +
Resend
+
+ +
+
+
+
+
+
+ +
+
+
+ + Save + +
+
+
+
+