Communication
Transactional email system with Brevo and Mailpit
Communication
What's Included
- Four transactional email templates (welcome, password reset, password changed, GitHub invite)
- Brevo integration for production emails
- Mailpit for local development (catches all outgoing emails)
- Environment-based adapter swap — no code changes between dev and prod
Email Architecture
Two adapters implement EmailSenderInterface:
| Environment | Adapter | Delivery |
|---|---|---|
| Production | BrevoTransactionalEmailSender | Brevo API with template IDs |
| Development | SymfonyMailerEmailSender | Symfony Mailer → Mailpit |
Both adapters implement the same domain port, keeping the application layer decoupled from the delivery mechanism. The swap is configured in config/services.yaml via environment-specific overrides.
Transactional Emails
| Trigger | Template Variables | |
|---|---|---|
| Welcome | User registration | userName, link (validation) |
| Password Reset | Forgot password request | userName, link (reset) |
| Password Changed | Password change or reset | userName |
| GitHub Membership | Paid subscription + invite | userName, organizationUrl |
All emails are triggered via domain events. If sending fails, the error is logged but does not block the originating action.
Brevo Setup (Production)
1. Create Templates
Create 4 transactional email templates in your Brevo dashboard using the template variables listed above.
2. Configure Template IDs
In config/packages/brevo.yaml:
parameters:
brevo_template_welcome: 1
brevo_template_password_changed: 2
brevo_template_password_reset: 3
brevo_template_github_membership: 4
Update the IDs to match your Brevo dashboard.
3. Set Environment Variables
BREVO_API_KEY=xkeysib-...
EMAIL_SENDER_EMAIL=noreply@yourdomain.com
EMAIL_SENDER_NAME="Your App Name"
Mailpit (Local Development)
In development, all emails are caught by Mailpit instead of being sent to real addresses. The Mailpit web UI is available at:
All emails sent during development appear here, making it easy to test email flows without configuring a real email provider.