Email sending schema
Business overview
Email notifications support our core journeys: onboarding, purchases, support, and re‑engagement. This document describes when each email is sent, to whom, and what content/template is used in Farfalla. Use it to align teams and troubleshoot issues.
Scope
- Channel: Email (excludes Slack notifications)
- Product areas: Storefront, Commerce, Identity/Access, Support, Reporting
- Source: Notification classes and jobs in
farfalla
Delivery & localization
- Delivery: Laravel Notifications via
->notify()/Notification::route('mail', ...). Some messages run queued (ShouldQueue) and some immediate (notifyNow). - From address: usually
no-reply@{tenant.domain}; exceptions noted below. - Templates: Blade Markdown templates under
resources/views/mail/**or the vendor notification templatevendor.notifications.email. - Locale: most emails respect tenant language (
tenant()->lang) and translation keys.
Trigger map (what, when, to whom, template)
Purchases and invoices
-
Issue purchase invoice
- Trigger: Order approved with content items and invoice email enabled.
- Class:
App\Notifications\IssueInvoice - Sender:
no-reply@{tenant.domain} - Recipient: Buyer (
order->user) - Template:
mail.issue.invoice - Content: Purchased issues (cover, reader link), help/FAQ links, app banners, recommended issues.
-
Plan/subscription invoice
- Trigger: Order approved with subscription items and invoice email enabled.
- Class:
App\Notifications\PlanInvoice - Sender:
no-reply@{tenant.domain} - Recipient: Subscriber (
order->user) - Template:
mail.plan.invoice - Content: Plan and coupon details, account/library/FAQ links, app banners.
-
Gift purchase status
- Trigger: Gift orders; subject and template vary by order status (
pending,approved,cancelled). - Class:
App\Notifications\GiftInvoice - Sender:
no-reply@{tenant.domain} - Recipient: Buyer
- Templates:
mail.gift.invoice-pending,mail.gift.invoice-success,mail.gift.invoice-rejected - Content: Issue, coupon, destination link (redeem or congrats), app banners.
- Trigger: Gift orders; subject and template vary by order status (
-
Sale notification (tenant)
- Trigger: Sale notification job dispatches an email with sale data.
- Class:
App\Notifications\NewSaleNotification - Sender:
no-reply@{tenant.domain} - Recipient: Configured email(s) in the job context
- Template:
mail.new-sale - Content: Sale metadata payload.
Shipping
- Shipping status update
- Trigger:
ShippingNote::dispatchNotification()on status changes (e.g., in‑transit, pickup, delivered, completed, cancelled). - Class:
App\Notifications\ShippingNoteNotification - Sender:
no-reply@{tenant.domain} - Recipient: Buyer (
order->user) - Template:
mail.shipping.note - Subject: Based on status translation (e.g.,
mail.shipping-note.status.delivered.title). - Content: Product list, shipping totals, addresses, costs.
- Trigger:
Identity & access
-
Welcome
- Trigger: After user registration.
- Class:
App\Notifications\WelcomeNotification - Sender:
no-reply@{tenant.domain} - Recipient: New user
- Template:
vendor.notifications.email - Content: Either “get started” (social login validated) or “verify email” (hash link).
-
Password reset
- Trigger: Password reset request.
User::sendPasswordResetNotification($token) - Class:
App\Notifications\CustomResetPassword - Sender:
no-reply@{tenant.domain} - Recipient: User
- Template:
vendor.notifications.email - Content: Reset CTA and explanatory lines.
- Trigger: Password reset request.
-
Login token (apps)
- Trigger: Publica Network temporary login code generation.
- Class:
App\Notifications\LoginTokenNotification - Sender:
no-reply@{tenant.domain} - Recipient: End user email
- Template:
mail.login-token - Content: One‑time code, expiration minutes, magic link, tenant/app assets.
Lifecycle & engagement
- Lifecycle drip
- Trigger: Scheduled job N days after signup for users without active subscription.
- Class:
App\Notifications\LifecycleNotification - Sender:
tenant('mails.notifications') - Recipient: Target user cohort
- Template:
mail.lifecycle-email - Content: Configurable subject/body from
LifecycleEmailrecord.
Reports & exports
- Export ready
- Trigger: Export file generated; job creates a temporary URL (valid ~1 week).
- Class:
App\Notifications\ExportReportGenerated - Sender:
no-reply@{platform.final_domain}(Publica.la) - Recipient: Requesting user email
- Template:
vendor.notifications.email - Content: Subject from job options, body message, download CTA.
Billing & finance
- Unpaid invoices (tenant)
- Trigger: Scheduled job; tenant with unpaid invoices.
- Class:
App\Notifications\UnpaidInvoices - Sender:
admin@publica.la - Recipient: Tenant owner email and billing contact (
tenant->meta.mails['payments']) - Template:
vendor.notifications.email - Content: Blocking date, link to billing settings.
Marketplace & holds
- Reserved issue available (PPU)
- Trigger: Budget available for reserved issue; batch job per tenant.
- Class:
App\Notifications\IssueAvailable - Sender: default
- Recipient: User with qualifying hold
- Template:
mail.issue.available - Content: Issue name and details with links.
Gateways
- Duplicate subscription detected (MercadoPago)
- Trigger: MercadoPago subscription event detects duplicate.
- Class:
App\Notifications\MPDuplicateSubscriptionNotification - Sender:
no-reply@{tenant.domain} - Recipient: Affected user
- Template:
vendor.notifications.email - Content: Cancel/refund notice and CTA to subscribe again.
Support
-
Storefront support request
- Trigger: End‑user submits help form.
- Class:
App\Notifications\UserSupportRequest - Sender: End‑user email (From)
- Recipient: Tenant support recipients (routed addresses)
- Template:
mail.support-request - Content: Subject, message, user email, registration date, subscription status, dashboard shortcut URL.
-
App support request (Reader apps)
- Trigger: App support flow in mobile/desktop.
- Class:
App\Notifications\AppSupportRequest - Sender: End‑user email (From)
- Recipient: Tenant support recipients
- Template:
mail.app-support-request - Content: App/device/versions, tenant context, user metadata, message.
Templates reference (views)
mail.issue.invoicemail.plan.invoicemail.gift.invoice-pending,mail.gift.invoice-success,mail.gift.invoice-rejectedmail.shipping.notemail.login-tokenmail.lifecycle-emailmail.support-requestmail.app-support-requestmail.issue.availablemail.new-salevendor.notifications.email(common generic layout)
Operational notes
- Queueing: Most notifications implement
ShouldQueue. Jobs like lifecycle, exports, unpaid invoices, and PPU holds batch work per tenant. - Localization: Several notifications call
->locale(tenant()->lang ?? 'en')at dispatch. - From/Reply‑To: Support requests deliberately use the end‑user’s address in the From header to ease ticket replies.
- Download links: Export links use temporary URLs with a 1‑week expiry.
Troubleshooting
- Not received: Verify
maildriver configuration, queue workers, and that the notification/job is enabled and dispatched. - Wrong language: Confirm tenant
langand where->locale(...)is applied on dispatch. - Wrong sender: Check per‑notification
from(...)and tenant domain settings. - Template mismatch: Ensure the expected Blade view exists and parameters are provided by the notification constructor.