Strapi Email & Notifications — Email Plugin Configuration and Template Customization
In this tutorial, you will learn how to configure Strapi's email plugin for sending transactional emails (password resets, confirmations, notifications), customize email templates, and send programmatic emails from your controllers and services.
What You'll Learn
- How to install and configure Strapi's email plugin
- How to configure SendGrid, SMTP, and other email providers
- How to customize email templates for user workflows
- How to send emails programmatically from services and controllers
- How to configure email notifications for content events
- Email deliverability best practices
Why It Matters
Emails are essential for user management (password resets, confirmations) and user engagement (notifications, digests). Strapi's email plugin integrates with major email providers and lets you send transactional emails with customizable templates directly from your Strapi backend.
Real-World Use
A community recipe platform sends emails when: a user registers (confirmation), a user resets their password, a recipe receives a new comment, or a user's recipe is featured. All emails use the site's branding and are sent through SendGrid for reliable delivery. The email plugin handles SMTP configuration, template rendering, and sending — all from within Strapi.
Learning Path
flowchart LR A["Admin Customization"] --> B["Email & Notifications
-- You are here"]:::current B --> C["Internationalization"] classDef current fill:#4945ff,color:#fff,stroke-width:2px
Email Plugin Installation
The email plugin may or may not be installed by default. Check and install if needed:
# Check if email plugin is installed
npm run strapi list
# Install the email plugin
npm run strapi install email
After installation, configure the email provider in config/plugins.js.
Email Provider Configuration
Strapi supports multiple email providers through community packages.
# Install SendGrid provider
npm install @strapi/provider-email-sendgrid
# Install Amazon SES provider
npm install @strapi/provider-email-amazon-ses
# Install Nodemailer provider (SMTP)
npm install @strapi/provider-email-nodemailer
SendGrid Configuration
// config/plugins.js
module.exports = {
email: {
config: {
provider: "sendgrid",
providerOptions: {
apiKey: process.env.SENDGRID_API_KEY,
},
settings: {
defaultFrom: "noreply@yourdomain.com",
defaultFromName: "Your App Name",
defaultReplyTo: "support@yourdomain.com",
defaultReplyToName: "Support Team",
},
},
},
};
SMTP (Nodemailer) Configuration
// config/plugins.js
module.exports = {
email: {
config: {
provider: "nodemailer",
providerOptions: {
host: process.env.SMTP_HOST || "smtp.gmail.com",
port: process.env.SMTP_PORT || 587,
secure: process.env.SMTP_SECURE === "true", // true for 465, false for others
auth: {
user: process.env.SMTP_USERNAME,
pass: process.env.SMTP_PASSWORD,
},
},
settings: {
defaultFrom: "noreply@yourdomain.com",
defaultFromName: "Your App Name",
},
},
},
};
Amazon SES Configuration
// config/plugins.js
module.exports = {
email: {
config: {
provider: "amazon-ses",
providerOptions: {
key: process.env.AWS_ACCESS_KEY_ID,
secret: process.env.AWS_SECRET_ACCESS_KEY,
amazon: "https://email.us-east-1.amazonaws.com",
},
settings: {
defaultFrom: "noreply@yourdomain.com",
defaultFromName: "Your App Name",
},
},
},
};
Sending Emails Programmatically
Send emails from your controllers, services, or lifecycle hooks:
// Send a simple email
await strapi.plugin("email").service("email").send({
to: "user@example.com",
from: "noreply@yourdomain.com",
replyTo: "support@yourdomain.com",
subject: "Welcome to our platform",
text: "Thank you for registering.",
html: "<h1>Welcome!</h1><p>Thank you for registering.</p>",
});
// Send with template variables
const user = { name: "Alice", email: "alice@example.com" };
await strapi.plugin("email").service("email").send({
to: user.email,
subject: "Welcome, ${user.name}!",
text: `Hi ${user.name},\n\nWelcome to the platform!`,
html: `<h1>Hi ${user.name}!</h1><p>Welcome to the platform!</p>`,
});
// In a controller — send email after article creation
async create(ctx) {
const { data } = ctx.request.body;
const article = await strapi.entityService.create("api::article.article", { data });
// Send notification to all editors
const editors = await strapi.entityService.findMany("plugin::users-permissions.user", {
filters: { role: { name: "Editor" } },
});
for (const editor of editors) {
await strapi.plugin("email").service("email").send({
to: editor.email,
subject: "New article created",
html: `<p>A new article <strong>${article.title}</strong> has been created.</p>`,
});
}
return { data: article };
}
Email Template Customization
Strapi's email templates are configured in the admin panel for user workflows:
// Admin panel: Settings > Users & Permissions > Email Templates
// Available templates:
// - Email confirmation
// - Password reset
// - Email address confirmation
// Each template supports these variables:
// - URL (confirmation/reset link)
// - USER (user object)
// - CODE (reset code)
// Customized password reset template (HTML):
`
<table style="max-width:600px;margin:0 auto;font-family:sans-serif">
<tr>
<td style="padding:40px;background:#f8fafc;border-radius:8px">
<h1 style="color:#1e293b">Reset Your Password</h1>
<p style="color:#64748b">Hi ${USER.username},</p>
<p style="color:#64748b">Click the button below to reset your password. This link expires in 1 hour.</p>
<a href="${URL}"
style="display:inline-block;padding:12px 24px;background:#4f46e5;color:#fff;text-decoration:none;border-radius:6px">
Reset Password
</a>
<p style="color:#94a3b8;margin-top:24px;font-size:12px">
If you did not request this, ignore this email.
</p>
</td>
</tr>
</table>
`
The email templates use ES6 template literals with ${} placeholders. Test each template thoroughly before production use.
Email from Lifecycle Hooks
Send automatic emails when content changes:
// src/api/article/content-types/article/lifecycle.js
module.exports = {
async afterCreate(event) {
const { result } = event;
const { strapi } = event;
// Notify subscribers about new article
const subscribers = await strapi.db.query("api::subscriber.subscriber").findMany({
where: { active: true },
});
const emailService = strapi.plugin("email").service("email");
for (const subscriber of subscribers) {
await emailService.send({
to: subscriber.email,
subject: `New article: ${result.title}`,
html: `
<h2>New Article Published</h2>
<p><strong>${result.title}</strong></p>
<p>${result.description?.substring(0, 200)}...</p>
<a href="https://example.com/articles/${result.id}">Read more</a>
`,
}).catch((err) => {
strapi.log.error(`Failed to send email to ${subscriber.email}: ${err.message}`);
});
}
},
};
Email Error Handling
Always handle email sending failures gracefully:
// Never let email failures crash your application
async function sendEmailSafe(recipient, subject, html) {
try {
await strapi.plugin("email").service("email").send({
to: recipient,
subject,
html,
});
return { success: true };
} catch (error) {
strapi.log.error(`Email delivery failed: ${error.message}`);
// Log to monitoring service
return { success: false, error: error.message };
}
}
// Use in controllers:
async create(ctx) {
try {
const entry = await strapi.entityService.create(...);
// Non-blocking email send
sendEmailSafe(
ctx.state.user.email,
"Entry created",
`<p>Your entry has been created.</p>`
);
return { data: entry };
} catch (error) {
return ctx.badRequest(error.message);
}
}
Testing Email Delivery
For development, use a test email service:
// config/plugins.js — Development email config (Mailtrap)
module.exports = {
email: {
config: {
provider: "nodemailer",
providerOptions: {
host: "sandbox.smtp.mailtrap.io",
port: 2525,
auth: {
user: process.env.MAILTRAP_USER,
pass: process.env.MAILTRAP_PASS,
},
},
settings: {
defaultFrom: "dev@example.com",
defaultFromName: "Dev Environment",
},
},
},
};
Mailtrap, Mailpit, or Mailhog capture emails in development so you can inspect them without sending real messages.
Common Mistakes
Not setting up email in development. Without email configuration, password reset and confirmation flows are broken. Use Mailtrap or similar services for development.
Hardcoding email provider credentials. API keys and SMTP passwords are sensitive. Store them in environment variables and never commit them to version control.
Not handling email sending failures. Email delivery can fail for many reasons (invalid address, provider error, rate limits). Always wrap email sending in try/catch and log failures.
Using unverified sender domains. Email providers require sender domain verification. Sending from unverified domains causes emails to land in spam or be rejected.
Not testing email templates on real email clients. HTML emails render differently across providers (Gmail, Outlook, Apple Mail). Test templates on multiple clients before production use.
Practice Questions
What are the supported email providers for Strapi? Answer: SendGrid, Amazon SES, Nodemailer (SMTP), and community providers. Each requires a specific npm package and configuration.
How do you send an email programmatically from a Strapi service? Answer: Use
strapi.plugin('email').service('email').send({ to, subject, text, html }). The email plugin provides a unified API regardless of the provider.Where do you customize the password reset email template? Answer: Settings > Users & Permissions > Email Templates in the admin panel. Each template supports variables like
${URL},${USER}, and${CODE}.Challenge: Build a complete email notification system: (1) Configure the email plugin with a real provider (SendGrid or SMTP), (2) Customize the password reset and email confirmation templates with your branding, (3) Create a lifecycle hook that sends a welcome email when a user registers, (4) Implement a "weekly digest" feature that emails subscribers a summary of the week's content, (5) Add email preferences to the User profile (which notifications they want to receive), (6) Test the complete flow with error handling.
FAQ
Mini Project
Your task: Set up a complete email notification pipeline.
- Configure the email plugin with Mailtrap for development (or SendGrid for production).
- Customize the password reset and email confirmation templates with your brand colors and logo.
- Create a lifecycle hook on the Article content type that:
- Sends a notification to all users with the "Editor" role when a new article is created
- Sends a "thank you" email to the author
- Create a custom service method
sendWeeklyDigestthat:- Queries articles published in the last week
- Sends a summary email to all subscribed users
- Includes article titles, descriptions, and links
- Test the entire flow by triggering each event and verifying the email content.
What's Next
Now that you understand email and notifications, proceed to Internationalization to learn how to configure the i18n plugin for multi-language content management. After that, explore advanced development topics like Lifecycle Hooks.
Related lessons:
- Node.js — How Strapi sends emails
- REST API — How email settings work via API
- WordPress Email Configuration — Compare email setup
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro