Email Templates
Every email your SaaS sends shapes your brand. A generic "Your password has been reset" feels impersonal. A well-crafted "You're back in, {name}" builds trust. This page lets you edit subjects, body copy, and active status for every transactional email your platform sends — without deploying code.
Why This Matters
Transactional emails have the highest open rates of any email type (often 60-80%). They are your most-read communication channel. Yet most SaaS products ship with generic templates and never touch them again. With editable templates, you can:
- A/B test your welcome email — Try different subject lines and body copy to see what drives users to complete onboarding.
- Match your brand voice — If your product is playful, your emails should be too. If you sell to enterprises, keep them professional.
- Respond to user feedback — Users complaining about too many emails? Disable specific notifications in one click. No code change, no deploy.
- Localize for different markets — Edit templates to match the language and tone of your target audience.
How It Works
The EmailTemplate model stores each template's subject and body with variable substitution. Variables are wrapped in curly braces and replaced with real values at send time:
Hello {name}, welcome to {app_name}!
Available Variables
All templates have access to these base variables:
{name}— The recipient's full name.{email}— The recipient's email address.{app_name}— Your platform name (from App settings). Changes automatically when you update the app name.
Some templates have additional variables depending on context:
{url}— An action URL (verification link, password reset link, magic link, invitation link). The most important variable — it is the call to action in the email.{org_name}— The organization name. Available in org-related emails (invitations, member removed, role changed).{role}— The role name. Available in invitation and role-change emails (e.g., "You've been invited as an admin").{token}— A raw token value. Available in templates where the link includes a token, in case you want to display it separately.
All 12 System Templates
The EmailTemplateSeeder creates these templates during setup. Each one corresponds to a specific moment in the user lifecycle:
Authentication Emails
- Email Verification — Sent when a user registers or changes their email address. Contains a verification link (
{url}). If this email does not arrive, the user cannot verify their account, so make sure your mail driver is working before you launch. - Password Reset — Sent when a user requests a password reset. Contains a time-limited reset link (
{url}). Keep this email short and clear — the user is frustrated and wants to get back in quickly. - Magic Link Login — Sent when a user requests a passwordless login link. Contains a single-use login link (
{url}). Only sent when magic link auth is enabled in Auth settings.
Onboarding Emails
- Welcome Email — Sent after a user completes registration and email verification. This is your first impression. Use it to guide the user toward their first success — link to a getting-started guide, highlight the one feature they should try first, or simply make them feel welcome. Variables:
{name},{app_name}.
Team & Organization Emails
- Organization Invitation — Sent when a team admin invites someone by email. Contains an invitation link (
{url}) and the role they are being invited to ({role}). The recipient might not have an account yet — the link handles both signup and invitation acceptance. Variables:{name},{org_name},{role},{url}. - Invitation Accepted — Sent to the person who sent the invitation when the invitee accepts. A small but meaningful notification — the inviter knows their teammate is onboard. Variables:
{name}(the invitee's name),{org_name}. - Member Removed — Sent to a user when they are removed from an organization. Keep this professional and neutral. Variables:
{name},{org_name}. - Role Changed — Sent when a user's role within an organization is changed (e.g., from member to admin). Variables:
{name},{org_name},{role}(the new role).
Account Status Emails
- Account Suspended — Sent when a super admin suspends a user's account. Explain why (if applicable) and how the user can appeal. Variables:
{name},{app_name}. - Account Unsuspended — Sent when a suspended account is reactivated. Let the user know they can log in again. Variables:
{name},{app_name}.
Billing Emails
- Subscription Created — Sent when an organization starts a paid subscription. Confirm what plan they are on, and link to billing settings. Variables:
{name},{org_name},{app_name}. - Subscription Cancelled — Sent when an organization cancels their subscription. This is your last chance to save them — consider including a link to a feedback survey or a direct reply to your support email. Variables:
{name},{org_name},{app_name}.
Managing Templates
List All Templates
GET /api/admin/email-templates
Returns all templates with their current subject, body, and active/inactive status.
Edit a Template
PUT /api/admin/email-templates/{id}
{
"subject": "Welcome to {app_name}, {name}!",
"body": "<h1>You're in!</h1><p>Hi {name}, your account is ready. Here's what to do first...</p>"
}
The body supports HTML. Use it to add structure, brand colors, and call-to-action buttons. Keep in mind that email HTML rendering is limited compared to web browsers — stick to tables, inline styles, and simple layouts.
Preview a Template
POST /api/admin/email-templates/{id}/preview
Renders the template with realistic sample data so you can see exactly how the email will look before saving. Variables are replaced with example values (e.g., {name} becomes "Jane Smith", {app_name} becomes your configured app name). Use this to catch formatting issues, broken HTML, and awkward copy before it reaches real users.
Send a Test Email
POST /api/admin/email-templates/{id}/test
{
"to": "you@example.com"
}
Sends a real, rendered email to the specified address using your currently configured mail driver. This tests two things at once: that your template looks correct in a real email client (Gmail, Outlook, Apple Mail), and that your mail driver is working. Always send yourself a test after editing a template.
Reset to Default
POST /api/admin/email-templates/{id}/reset
Restores the template to its original content from the seeder. Experimented too much and the template is a mess? Reset it in one click and start over. This does not affect emails that have already been sent.
Active / Inactive Toggle
POST /api/admin/email-templates/{id}/toggle
When a template is set to inactive, the corresponding email is simply not sent. The system skips it silently. Use this when:
- Users are complaining about too many emails — disable the ones they find noisy (e.g., "invitation accepted" notifications).
- You want to temporarily stop a specific notification during maintenance.
- You have a template for a feature that is not ready yet and you do not want it firing accidentally.
Critical emails like password reset and email verification should generally stay active. If you disable them, users will not be able to recover their accounts.
For Developers: Under the Hood
If you are building new features that send emails and want them to use the template system, two classes handle the integration:
UsesEmailTemplatetrait — Add this trait to any Laravel Notification class. It automatically looks up the corresponding email template from the database, substitutes variables, and checks whether the template is active before sending. If the template is inactive, the notification is silently skipped.TemplateMailclass — A Mailable that renders a template with the provided variables. Used internally by the trait, but you can also use it directly if you need to send a templated email outside the notification system (e.g., from a job or controller).
To add a new email template, create a new record in the EmailTemplateSeeder with a unique slug, default subject, default body, and the list of available variables. Then reference that slug in your notification class.