diff --git a/app/Domains/MailTest/Controllers/MailTestController.php b/app/Domains/MailTest/Controllers/MailTestController.php
index 6e5ce5b..ee0f07e 100644
--- a/app/Domains/MailTest/Controllers/MailTestController.php
+++ b/app/Domains/MailTest/Controllers/MailTestController.php
@@ -4,6 +4,7 @@ namespace App\Domains\MailTest\Controllers;
use App\Domains\MailTest\Requests\SendTestMailRequest;
use App\Domains\MailTest\Services\MailTestService;
+use App\Domains\Tenant\Models\Tenant;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
@@ -13,10 +14,15 @@ class MailTestController extends Controller
protected MailTestService $mailTestService,
) {}
- public function __invoke(SendTestMailRequest $request): JsonResponse
+ public function __invoke(SendTestMailRequest $request, string $tenantCode): JsonResponse
{
+ $tenant = Tenant::query()
+ ->where('codigo', $tenantCode)
+ ->firstOrFail();
+
return response()->json(
$this->mailTestService->send(
+ $tenant,
$request->validated('to'),
$request->validated('subject'),
$request->validated('message'),
diff --git a/app/Domains/MailTest/Mailables/TestMail.php b/app/Domains/MailTest/Mailables/TestMail.php
index 182f00f..fd0e1fb 100644
--- a/app/Domains/MailTest/Mailables/TestMail.php
+++ b/app/Domains/MailTest/Mailables/TestMail.php
@@ -2,6 +2,7 @@
namespace App\Domains\MailTest\Mailables;
+use App\Domains\Tenant\Models\Tenant;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
@@ -15,6 +16,7 @@ class TestMail extends Mailable
public function __construct(
public readonly string $mailSubject,
public readonly string $mailMessage,
+ public readonly Tenant $tenant,
) {}
public function envelope(): Envelope
@@ -24,14 +26,15 @@ class TestMail extends Mailable
public function content(): Content
{
- $message = nl2br(e($this->mailMessage));
+ $this->tenant->loadMissing(['headerLogo', 'footerLogo']);
return new Content(
- htmlString: <<Prueba de correo de Shopit
-
{$message}
- Si recibiste este mensaje, la configuracion de correo funciona correctamente.
- HTML,
+ view: 'mail.test',
+ with: [
+ 'tenant' => $this->tenant,
+ 'headerLogoUrl' => $this->tenant->headerLogo?->getTemporaryUrl(1440),
+ 'footerLogoUrl' => $this->tenant->footerLogo?->getTemporaryUrl(1440),
+ ],
);
}
}
diff --git a/app/Domains/MailTest/Services/MailTestService.php b/app/Domains/MailTest/Services/MailTestService.php
index e1201f3..e3793b4 100644
--- a/app/Domains/MailTest/Services/MailTestService.php
+++ b/app/Domains/MailTest/Services/MailTestService.php
@@ -3,6 +3,7 @@
namespace App\Domains\MailTest\Services;
use App\Domains\MailTest\Mailables\TestMail;
+use App\Domains\Tenant\Models\Tenant;
use Illuminate\Support\Facades\Mail;
class MailTestService
@@ -10,16 +11,17 @@ class MailTestService
/**
* @return array
*/
- public function send(string $recipient, ?string $subject = null, ?string $message = null): array
+ public function send(Tenant $tenant, string $recipient, ?string $subject = null, ?string $message = null): array
{
$subject ??= 'Prueba de correo de Shopit';
$message ??= 'Este es un correo de prueba enviado desde Shopit.';
- Mail::to($recipient)->send(new TestMail($subject, $message));
+ Mail::to($recipient)->send(new TestMail($subject, $message, $tenant));
return [
'message' => 'Correo de prueba enviado correctamente.',
'recipient' => $recipient,
+ 'tenant_code' => $tenant->codigo,
'mailer' => (string) config('mail.default'),
'sent_at' => now()->toIso8601String(),
];
diff --git a/app/Domains/MailTest/routes/api.php b/app/Domains/MailTest/routes/api.php
index d26b474..a75d512 100644
--- a/app/Domains/MailTest/routes/api.php
+++ b/app/Domains/MailTest/routes/api.php
@@ -3,4 +3,4 @@
use App\Domains\MailTest\Controllers\MailTestController;
use Illuminate\Support\Facades\Route;
-Route::post('mail-test/send', MailTestController::class);
+Route::post('{tenant_code}/mail-test/send', MailTestController::class);
diff --git a/resources/views/components/mail/branded-layout.blade.php b/resources/views/components/mail/branded-layout.blade.php
new file mode 100644
index 0000000..c612670
--- /dev/null
+++ b/resources/views/components/mail/branded-layout.blade.php
@@ -0,0 +1,49 @@
+@props(['tenant', 'headerLogoUrl' => null, 'footerLogoUrl' => null])
+
+
+
+
+
+
+
+ {{ $tenant->nombre }}
+
+
+
+
+
+
+
+
+
+ @if ($headerLogoUrl)
+
+ @else
+ {{ $tenant->nombre }}
+ @endif
+ |
+
+
+ |
+ {{ $slot }}
+ |
+
+
+
+ @if ($footerLogoUrl)
+
+ @endif
+ {{ $footer ?? 'Este correo fue enviado por '.$tenant->nombre.'.' }}
+ |
+
+
+ |
+
+
+
+
diff --git a/resources/views/mail/test.blade.php b/resources/views/mail/test.blade.php
new file mode 100644
index 0000000..ba5d695
--- /dev/null
+++ b/resources/views/mail/test.blade.php
@@ -0,0 +1,11 @@
+
+
+ Prueba de correo de Shopit
+
+
+ {!! nl2br(e($mailMessage)) !!}
+
+
+ Si recibiste este mensaje, la configuración de correo funciona correctamente.
+
+
diff --git a/tests/Feature/MailTest/MailTestControllerTest.php b/tests/Feature/MailTest/MailTestControllerTest.php
index bfc2bcc..0b67cf2 100644
--- a/tests/Feature/MailTest/MailTestControllerTest.php
+++ b/tests/Feature/MailTest/MailTestControllerTest.php
@@ -2,17 +2,24 @@
namespace Tests\Feature\MailTest;
+use App\Domains\Attachable\Enums\AttachmentType;
+use App\Domains\Attachable\Models\Attachment;
use App\Domains\MailTest\Mailables\TestMail;
+use App\Domains\Tenant\Models\Tenant;
+use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
class MailTestControllerTest extends TestCase
{
+ use RefreshDatabase;
+
public function test_it_sends_a_test_email(): void
{
Mail::fake();
+ $tenant = $this->createTenant();
- $response = $this->postJson('/api/mail-test/send', [
+ $response = $this->postJson('/api/acme/mail-test/send', [
'to' => 'recipient@example.com',
'subject' => 'SMTP test',
'message' => 'Test message',
@@ -21,21 +28,24 @@ class MailTestControllerTest extends TestCase
$response->assertOk()
->assertJsonPath('message', 'Correo de prueba enviado correctamente.')
->assertJsonPath('recipient', 'recipient@example.com')
+ ->assertJsonPath('tenant_code', 'acme')
->assertJsonPath('mailer', 'array')
->assertJsonStructure(['sent_at']);
- Mail::assertSent(TestMail::class, function (TestMail $mail): bool {
+ Mail::assertSent(TestMail::class, function (TestMail $mail) use ($tenant): bool {
return $mail->hasTo('recipient@example.com')
&& $mail->mailSubject === 'SMTP test'
- && $mail->mailMessage === 'Test message';
+ && $mail->mailMessage === 'Test message'
+ && $mail->tenant->is($tenant);
});
}
public function test_it_uses_default_content_when_optional_fields_are_omitted(): void
{
Mail::fake();
+ $this->createTenant();
- $this->postJson('/api/mail-test/send', [
+ $this->postJson('/api/acme/mail-test/send', [
'to' => 'recipient@example.com',
])->assertOk();
@@ -48,12 +58,110 @@ class MailTestControllerTest extends TestCase
public function test_it_validates_the_recipient(): void
{
Mail::fake();
+ $this->createTenant();
- $this->postJson('/api/mail-test/send', [
+ $this->postJson('/api/acme/mail-test/send', [
'to' => 'invalid-email',
])->assertUnprocessable()
->assertJsonValidationErrors(['to']);
Mail::assertNothingSent();
}
+
+ public function test_the_mail_template_uses_the_tenant_branding(): void
+ {
+ $tenant = new Tenant([
+ 'codigo' => 'tenant-store',
+ 'nombre' => 'Tenant Store',
+ 'primary_color' => '#778899',
+ 'header_bg_color' => '#112233',
+ 'footer_bg_color' => '#445566',
+ ]);
+
+ $tenant->setRelation('headerLogo', new class extends Attachment
+ {
+ public function getTemporaryUrl(int $expiresInMinutes = 10): string
+ {
+ return 'https://example.com/header-logo.png';
+ }
+ });
+ $tenant->setRelation('footerLogo', new class extends Attachment
+ {
+ public function getTemporaryUrl(int $expiresInMinutes = 10): string
+ {
+ return 'https://example.com/footer-logo.png';
+ }
+ });
+
+ $mail = new TestMail(
+ 'Branded email',
+ 'Tenant message',
+ $tenant,
+ );
+
+ $html = $mail->render();
+
+ $this->assertStringContainsString('https://example.com/header-logo.png', $html);
+ $this->assertStringContainsString('https://example.com/footer-logo.png', $html);
+ $this->assertStringContainsString('background-color: #112233', $html);
+ $this->assertStringContainsString('background-color: #445566', $html);
+ $this->assertStringContainsString('color: #778899', $html);
+ $this->assertStringContainsString('Tenant Store', $html);
+ $this->assertStringContainsString('Tenant message', $html);
+ }
+
+ public function test_it_returns_not_found_for_an_unknown_tenant(): void
+ {
+ Mail::fake();
+
+ $this->postJson('/api/unknown/mail-test/send', [
+ 'to' => 'recipient@example.com',
+ ])->assertNotFound();
+
+ Mail::assertNothingSent();
+ }
+
+ public function test_it_does_not_resolve_the_tenant_by_id(): void
+ {
+ Mail::fake();
+ $tenant = $this->createTenant();
+
+ $this->postJson("/api/{$tenant->id}/mail-test/send", [
+ 'to' => 'recipient@example.com',
+ ])->assertNotFound();
+
+ Mail::assertNothingSent();
+ }
+
+ private function createTenant(): Tenant
+ {
+ $headerLogo = Attachment::create([
+ 'path' => 'tenants/header.png',
+ 'filename' => 'header.png',
+ 'type' => AttachmentType::Image,
+ 'mime_type' => 'image/png',
+ 'extension' => 'png',
+ ]);
+ $footerLogo = Attachment::create([
+ 'path' => 'tenants/footer.png',
+ 'filename' => 'footer.png',
+ 'type' => AttachmentType::Image,
+ 'mime_type' => 'image/png',
+ 'extension' => 'png',
+ ]);
+
+ return Tenant::create([
+ 'codigo' => 'acme',
+ 'nombre' => 'Acme Store',
+ 'dominio' => 'acme.example.com',
+ 'primary_color' => '#778899',
+ 'secondary_color' => '#64748b',
+ 'danger_color' => '#dc2626',
+ 'success_color' => '#16a34a',
+ 'header_bg_color' => '#112233',
+ 'footer_bg_color' => '#445566',
+ 'header_logo_id' => $headerLogo->id,
+ 'footer_logo_id' => $footerLogo->id,
+ ]);
+ }
}