Resend Email
Transactional email delivery via the Resend API. Handles all outbound email communication including password resets, magic links, portal invitations, document reminders, and billing emails.
Architecture
| Component | Path |
|---|---|
| Email config | backend/src/lib/email/config.ts (env loading, catch-all parsing) |
| Email client | backend/src/lib/email/index.ts |
| Email service | backend/src/lib/services/email.ts |
| Email templates | backend/src/lib/email-templates/ |
| Intent-based notification service | backend/src/lib/notifications/notification-service.ts |
| Queue processors | backend/src/lib/jobs/processors/notifications.ts, document-reminder.ts, billing-email.ts |
| Admin template table | documentObtainingEmailTemplates (document_obtaining_email_templates) |
Configuration
| Variable | Purpose |
|---|---|
RESEND_API_KEY | Resend API authentication |
EMAIL_FROM_ADDRESS | Sender (default: noreply@notifications.renewa.de) |
EMAIL_CATCH_ALL_ADDRESSES | Comma-separated redirect targets (max 10, validated) |
EMAIL_ALLOW_REAL_DELIVERY | true enables delivery to actual recipients |
Secrets live in Infisical (EU) and sync natively to Fly.io. See Deployment Pipeline.
Delivery Safety
Like MessageBird SMS, delivery is flag-gated: unless EMAIL_ALLOW_REAL_DELIVERY=true, every email is redirected to the catch-all addresses (resolveRecipient in lib/email/config.ts). Each environment has a default catch-all mailbox renewa-one-<env>@renewa.de (local, test, preview, development, staging, production).
Email Types
Templates in backend/src/lib/email-templates/ (shared layout in base.ts):
| Template | Trigger |
|---|---|
password-reset | User requests reset |
magic-link | User requests magic link login |
email-verification | Email address verification |
welcome-email | Portal invitation / account creation |
document-reminder | Automated document follow-up |
new-document-requests | New document collection request |
escalation-urgent / escalation-last | Reminder escalation steps |
rejection-bundle | Bundled document rejection notice |
help-response | Help/support response |
Billing emails (invoices etc.) go through backend/src/services/billing/billing-email-service-impl.ts and the billing-email job processor.
Admin-Configurable Templates
The documentObtainingEmailTemplates table allows admins to customize email content for Document Obtaining workflows without code changes. Managed via Admin Dashboard.
Background Processing
Emails are sent asynchronously via the BullMQ notification queue to avoid blocking request handlers:
- Caller enqueues an email job (directly or via the intent-based
NotificationServiceImpl) - Background Jobs processor (
processors/notifications.ts,channel === 'email') picks up the job - Resend API is called with the rendered template
- Success/failure is logged; failed sends are retried by the job processor
Template Rendering
Templates use bilingual content following the Internationalization pattern. The recipient’s preferred language determines which version is sent.
Error Handling
- Failed sends are retried by the job processor
- Permanent failures are logged and reported to Sentry
Related
- Notifications — Notification dispatch architecture
- Portal — Portal invitation emails
- Document Obtaining — Document reminder emails
- Authentication — Password reset and magic link emails
- Background Jobs — Async email processing queue
- External Integrations — All third-party integrations
- Sentry — Delivery failure tracking