6.7 KiB
Story 8.1: Email Infrastructure Setup
Epic Reference
Epic 8: Email Notification System
Story Context
This is the foundational story for Epic 8. All subsequent email stories (8.2-8.10) depend on this infrastructure being complete. No other stories in Epic 8 can be implemented until this story is done.
User Story
As a developer, I want to configure email sending infrastructure and base templates, So that all emails have consistent branding and reliable delivery.
Acceptance Criteria
SMTP Configuration
- MAIL_MAILER configured via .env
- MAIL_HOST, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD
- MAIL_ENCRYPTION (TLS)
- MAIL_FROM_ADDRESS: no-reply@libra.ps
- MAIL_FROM_NAME: Libra Law Firm / مكتب ليبرا للمحاماة
Base Email Template
- Libra logo in header
- Navy blue (#0A1F44) and gold (#D4AF37) colors
- Professional typography
- Footer with firm contact info
- Mobile-responsive layout
Technical Setup
- Plain text fallback generation (auto-generated from HTML)
- Queue configuration for async sending (database driver)
- Email logging for debugging (log channel)
Implementation Steps
Step 1: Publish Laravel Mail Views
php artisan vendor:publish --tag=laravel-mail
This creates resources/views/vendor/mail/ with customizable templates.
Step 2: Create Base Mailable Class
Create app/Mail/BaseMailable.php:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
abstract class BaseMailable extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public function envelope(): Envelope
{
return new Envelope(
from: new \Illuminate\Mail\Mailables\Address(
config('mail.from.address'),
$this->getFromName()
),
);
}
protected function getFromName(): string
{
$locale = $this->locale ?? app()->getLocale();
return $locale === 'ar' ? 'مكتب ليبرا للمحاماة' : 'Libra Law Firm';
}
}
Step 3: Configure Queue for Email
Ensure config/queue.php uses the database driver and run:
php artisan queue:table
php artisan migrate
Step 4: Update Environment Variables
Add to .env.example:
MAIL_MAILER=smtp
MAIL_HOST=
MAIL_PORT=587
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=no-reply@libra.ps
MAIL_FROM_NAME="Libra Law Firm"
QUEUE_CONNECTION=database
Step 5: Create Email Logo Asset
Place the email logo at public/images/logo-email.png (120px height recommended for email clients).
Step 6: Customize Mail Templates
Modify resources/views/vendor/mail/html/header.blade.php:
<tr>
<td class="header" style="background-color: #0A1F44; padding: 25px; text-align: center;">
<a href="{{ config('app.url') }}" style="display: inline-block;">
<img src="{{ asset('images/logo-email.png') }}" alt="Libra Law Firm" height="45" style="height: 45px;">
</a>
</td>
</tr>
Modify resources/views/vendor/mail/html/themes/default.css for brand colors:
- Primary background: #0A1F44 (navy)
- Accent/buttons: #D4AF37 (gold)
- Button text: #0A1F44 (navy on gold)
Step 7: Configure Email Logging
In config/logging.php, ensure a channel exists for mail debugging. Emails are automatically logged when using the log mail driver for local testing.
Error Handling
- SMTP Connection Failures: Queue will retry failed jobs automatically (3 attempts by default)
- Configure retry delay in
config/queue.phpunderretry_after - Failed jobs go to
failed_jobstable for inspection - Monitor queue with
php artisan queue:failedto see failed emails
Technical Notes
Files to Create/Modify
| File | Action |
|---|---|
app/Mail/BaseMailable.php |
Create |
resources/views/vendor/mail/html/header.blade.php |
Modify |
resources/views/vendor/mail/html/footer.blade.php |
Modify |
resources/views/vendor/mail/html/themes/default.css |
Modify |
public/images/logo-email.png |
Create/Add |
.env.example |
Update |
config/mail.php |
Verify defaults |
Queue Configuration
This project uses the database queue driver for reliability. Ensure queue worker runs in production:
php artisan queue:work --queue=default
Local Testing
For local development, use the log mail driver:
MAIL_MAILER=log
Emails will appear in storage/logs/laravel.log.
For visual testing, consider Mailpit or similar (optional):
MAIL_MAILER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
Testing Requirements
Test Scenarios
Create tests/Feature/Mail/BaseMailableTest.php:
- SMTP configuration validates - Verify mail config loads correctly
- Base template renders with branding - Logo, colors visible in HTML output
- Plain text fallback generates - HTML converts to readable plain text
- Emails queue successfully - Job dispatches to queue, not sent synchronously
- Arabic sender name works - "مكتب ليبرا للمحاماة" when locale is 'ar'
- English sender name works - "Libra Law Firm" when locale is 'en'
- Failed emails retry - Queue retries on temporary failure
Example Test Structure
<?php
use App\Mail\BaseMailable;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Queue;
test('emails are queued not sent synchronously', function () {
Queue::fake();
// Send a test email extending BaseMailable
// Assert job was pushed to queue
});
test('sender name is arabic when locale is ar', function () {
app()->setLocale('ar');
// Create mailable and check from name
// expect($mailable->getFromName())->toBe('مكتب ليبرا للمحاماة');
});
test('sender name is english when locale is en', function () {
app()->setLocale('en');
// Create mailable and check from name
// expect($mailable->getFromName())->toBe('Libra Law Firm');
});
Definition of Done
- SMTP sending works (verified with real credentials or log driver)
- Base template displays Libra branding (logo, navy/gold colors)
- Plain text fallback auto-generates from HTML
- Emails dispatch to queue (not sent synchronously)
- Queue worker processes emails successfully
- All tests pass
- Code formatted with Pint
Dependencies
- Requires: None (foundational story)
- Blocks: Stories 8.2-8.10 (all other email stories)
Estimation
Complexity: Medium | Effort: 3-4 hours