better emails

This commit is contained in:
Andras Bacsai
2023-09-01 15:52:18 +02:00
parent 76510b8971
commit 3fa53556f4
28 changed files with 374 additions and 139 deletions

View File

@@ -0,0 +1,184 @@
<?php
namespace App\Console\Commands;
use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\ScheduledDatabaseBackup;
use App\Models\StandalonePostgresql;
use App\Models\TeamInvitation;
use App\Models\User;
use App\Notifications\Application\DeploymentFailed;
use App\Notifications\Application\DeploymentSuccess;
use App\Notifications\Application\StatusChanged;
use App\Notifications\Database\BackupFailed;
use App\Notifications\Database\BackupSuccess;
use App\Notifications\Test;
use App\Notifications\TransactionalEmails\InvitationLink;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage;
use Mail;
use Str;
use function Laravel\Prompts\select;
class TestEmail extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'email:test';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send a test email to the admin';
/**
* Execute the console command.
*/
private ?MailMessage $mail = null;
public function handle()
{
$email = select(
'Which Email should be sent?',
options: [
'emails-test' => 'Test',
'application-deployment-success' => 'Application - Deployment Success',
'application-deployment-failed' => 'Application - Deployment Failed',
'application-status-changed' => 'Application - Status Changed',
'backup-success' => 'Database - Backup Success',
'backup-failed' => 'Database - Backup Failed',
'invitation-link' => 'Invitation Link',
'waitlist-invitation-link' => 'Waitlist Invitation Link',
'waitlist-confirmation' => 'Waitlist Confirmation',
],
);
$type = set_transanctional_email_settings();
if (!$type) {
throw new Exception('No email settings found.');
}
$this->mail = new MailMessage();
$this->mail->subject("Test Email");
switch ($email) {
case 'emails-test':
$this->mail = (new Test())->toMail();
break;
case 'application-deployment-success':
$application = Application::all()->first();
$this->mail = (new DeploymentSuccess($application, 'test'))->toMail();
$this->sendEmail();
break;
case 'application-deployment-failed':
$application = Application::all()->first();
$preview = ApplicationPreview::all()->first();
if (!$preview) {
$preview = ApplicationPreview::create([
'application_id' => $application->id,
'pull_request_id' => 1,
'pull_request_html_url' => 'http://example.com',
'fqdn' => $application->fqdn,
]);
}
$this->mail = (new DeploymentFailed($application, 'test'))->toMail();
$this->sendEmail();
$this->mail = (new DeploymentFailed($application, 'test', $preview))->toMail();
$this->sendEmail();
break;
case 'application-status-changed':
$application = Application::all()->first();
$this->mail = (new StatusChanged($application))->toMail();
$this->sendEmail();
break;
case 'backup-failed':
$backup = ScheduledDatabaseBackup::all()->first();
$db = StandalonePostgresql::all()->first();
if (!$backup) {
$backup = ScheduledDatabaseBackup::create([
'enabled' => true,
'frequency' => 'daily',
'save_s3' => false,
'database_id' => $db->id,
'database_type' => $db->getMorphClass(),
'team_id' => 0,
]);
}
$output = 'Because of an error, the backup of the database ' . $db->name . ' failed.';
$this->mail = (new BackupFailed($backup, $db, $output))->toMail();
$this->sendEmail();
break;
case 'backup-success':
$backup = ScheduledDatabaseBackup::all()->first();
$db = StandalonePostgresql::all()->first();
if (!$backup) {
$backup = ScheduledDatabaseBackup::create([
'enabled' => true,
'frequency' => 'daily',
'save_s3' => false,
'database_id' => $db->id,
'database_type' => $db->getMorphClass(),
'team_id' => 0,
]);
}
$this->mail = (new BackupSuccess($backup, $db))->toMail();
$this->sendEmail();
break;
case 'invitation-link':
$user = User::all()->first();
$invitation = TeamInvitation::whereEmail($user->email)->first();
if (!$invitation) {
$invitation = TeamInvitation::create([
'uuid' => Str::uuid(),
'email' => $user->email,
'team_id' => 1,
'link' => 'http://example.com',
]);
}
$this->mail = (new InvitationLink($user))->toMail();
$this->sendEmail();
break;
case 'waitlist-invitation-link':
$this->mail = new MailMessage();
$this->mail->view('emails.waitlist-invitation', [
'email' => 'test2@example.com',
'password' => "supersecretpassword",
]);
$this->mail->subject('Congratulations! You are invited to join Coolify Cloud.');
$this->sendEmail();
break;
case 'waitlist-confirmation':
$this->mail = new MailMessage();
$this->mail->view(
'emails.waitlist-confirmation',
[
'confirmation_url' => 'http://example.com',
'cancel_url' => 'http://example.com',
]
);
$this->mail->subject('You are on the waitlist!');
$this->sendEmail();
break;
}
}
private function sendEmail()
{
Mail::send(
[],
[],
fn (Message $message) => $message
->from(
'internal@example.com',
'Test Email',
)
->to('test@example.com')
->subject($this->mail->subject)
->html((string)$this->mail->render())
);
}
}

View File

@@ -4,15 +4,7 @@ namespace App\Models;
class ApplicationPreview extends BaseModel
{
protected $fillable = [
'uuid',
'pull_request_id',
'pull_request_html_url',
'pull_request_issue_comment_id',
'fqdn',
'status',
'application_id',
];
protected $guarded = [];
static function findPreviewByApplicationAndPullId(int $application_id, int $pull_request_id)
{

View File

@@ -18,15 +18,15 @@ class DeploymentFailed extends Notification implements ShouldQueue
public Application $application;
public string $deployment_uuid;
public ApplicationPreview|null $preview;
public ?ApplicationPreview $preview = null;
public string $application_name;
public string|null $deployment_url = null;
public ?string $deployment_url = null;
public string $project_uuid;
public string $environment_name;
public string|null $fqdn;
public ?string $fqdn = null;
public function __construct(Application $application, string $deployment_uuid, ApplicationPreview|null $preview)
public function __construct(Application $application, string $deployment_uuid, ?ApplicationPreview $preview = null)
{
$this->application = $application;
$this->deployment_uuid = $deployment_uuid;
@@ -67,9 +67,8 @@ class DeploymentFailed extends Notification implements ShouldQueue
$mail->subject('❌ Deployment failed of ' . $this->application_name . '.');
} else {
$fqdn = $this->preview->fqdn;
$mail->subject('❌ Pull request #' . $this->preview->pull_request_id . ' of ' . $this->application_name . ' deployment failed.');
$mail->subject('❌ Deployment failed of pull request #' . $this->preview->pull_request_id . ' of ' . $this->application_name . '.');
}
$mail->view('emails.application-deployment-failed', [
'name' => $this->application_name,
'fqdn' => $fqdn,

View File

@@ -20,35 +20,33 @@ class EmailChannel
}
$mailMessage = $notification->toMail($notifiable);
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())
);
}
// if ($this->isResend) {
Mail::send(
[],
[],
fn (Message $message) => $message
->from(
data_get($notifiable, 'smtp_from_address'),
data_get($notifiable, 'smtp_from_name'),
)
->to($recepients)
->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

View File

@@ -26,33 +26,33 @@ 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'),
)
->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())
);
}
// if ($this->isResend) {
Mail::send(
[],
[],
fn (Message $message) => $message
->from(
data_get($settings, 'smtp_from_address'),
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

View File

@@ -14,12 +14,13 @@ class BackupFailed extends Notification implements ShouldQueue
{
use Queueable;
public string $message = 'Backup FAILED';
public string $name;
public string $frequency;
public function __construct(ScheduledDatabaseBackup $backup, public $database, public $output)
{
$this->message = "❌ Database backup for {$database->name} with frequency of $backup->frequency was FAILED.\n\nReason: $output";
$this->name = $database->name;
$this->frequency = $backup->frequency;
}
public function via(object $notifiable): array
@@ -36,20 +37,23 @@ class BackupFailed extends Notification implements ShouldQueue
if ($isDiscordEnabled && $isSubscribedToDiscordEvent) {
$channels[] = DiscordChannel::class;
}
ray($channels);
return $channels;
}
public function toMail(): MailMessage
{
$mail = new MailMessage();
$mail->subject("❌ Backup FAILED for {$this->database->name}");
$mail->line($this->message);
$mail->subject(" [ACTION REQUIRED] Backup FAILED for {$this->database->name}");
$mail->view('emails.backup-failed', [
'name' => $this->name,
'frequency' => $this->frequency,
'output' => $this->output,
]);
return $mail;
}
public function toDiscord(): string
{
return $this->message;
return "❌ Database backup for {$this->name} with frequency of {$this->frequency} was FAILED.\n\nReason: {$this->output}";
}
}

View File

@@ -14,12 +14,13 @@ class BackupSuccess extends Notification implements ShouldQueue
{
use Queueable;
public string $message = 'Backup Success';
public string $name;
public string $frequency;
public function __construct(ScheduledDatabaseBackup $backup, public $database)
{
$this->message = "✅ Database backup for {$database->name} with frequency of $backup->frequency was successful.";
$this->name = $database->name;
$this->frequency = $backup->frequency;
}
public function via(object $notifiable): array
@@ -42,13 +43,16 @@ class BackupSuccess extends Notification implements ShouldQueue
public function toMail(): MailMessage
{
$mail = new MailMessage();
$mail->subject("✅ Backup success for {$this->database->name}");
$mail->line($this->message);
$mail->subject("✅ Backup successfully done for {$this->database->name}");
$mail->view('emails.backup-success', [
'name' => $this->name,
'frequency' => $this->frequency,
]);
return $mail;
}
public function toDiscord(): string
{
return $this->message;
return "✅ Database backup for {$this->name} with frequency of {$this->frequency} was successful.";
}
}

View File

@@ -36,7 +36,7 @@ class Test extends Notification implements ShouldQueue
public function toMail(): MailMessage
{
$mail = new MailMessage();
$mail->subject("Coolify Test Notification");
$mail->subject("Test Email");
$mail->view('emails.test');
return $mail;
}

View File

@@ -20,16 +20,19 @@ class InvitationLink extends Notification implements ShouldQueue
return [TransactionalEmailChannel::class];
}
public function toMail(User $user): MailMessage
public function __construct(public User $user)
{
$invitation = TeamInvitation::whereEmail($user->email)->first();
}
public function toMail(): MailMessage
{
$invitation = TeamInvitation::whereEmail($this->user->email)->first();
$invitation_team = Team::find($invitation->team->id);
$mail = new MailMessage();
$mail->subject('Invitation for ' . $invitation_team->name);
$mail->view('emails.invitation-link', [
'team' => $invitation_team->name,
'email' => $user->email,
'email' => $this->user->email,
'invitation_link' => $invitation->link,
]);
return $mail;

View File

@@ -24,7 +24,7 @@ class Test extends Notification implements ShouldQueue
public function toMail(): MailMessage
{
$mail = new MailMessage();
$mail->subject('Test Notification');
$mail->subject('Test Email');
$mail->view('emails.test');
return $mail;
}