Strapi's email plugin is on by default but ships with the sendmail provider, which needs a mail server on the same machine. Switching to the official Nodemailer provider sends password resets, account confirmations and your own emails through Postwing instead.
| Setting | Value |
|---|---|
| SMTP host | smtp.postwing.app |
| Port | 587 |
| Encryption | STARTTLS (the connection is upgraded to TLS before login) |
| Username | The login of an SMTP token for your domain |
| Password | The password of that token — shown once, when the token is created |
npm install @strapi/provider-email-nodemailerKeep the credentials in the environment:
SMTP_HOST=smtp.postwing.app
SMTP_PORT=587
SMTP_USERNAME=token-login@your-domain.com
SMTP_PASSWORD=your-token-password Then point the email plugin at the provider. Use config/plugins.js with module.exports if your project is JavaScript:
export default ({ env }) => ({
email: {
config: {
provider: "nodemailer",
providerOptions: {
host: env("SMTP_HOST"),
port: env.int("SMTP_PORT", 587),
secure: false, // STARTTLS on 587; true for 465
auth: {
user: env("SMTP_USERNAME"),
pass: env("SMTP_PASSWORD"),
},
},
settings: {
defaultFrom: "Acme <noreply@your-domain.com>",
defaultReplyTo: "support@your-domain.com",
},
},
},
});defaultFrom must be on your verified domain, or DKIM and SPF will not align. Restart Strapi after changing the file.
Password reset and email confirmation messages do not use defaultFrom. Open Settings → Users & Permissions plugin → Email templates and edit both templates:
| Field | Value |
|---|---|
| Shipper name | Your product name |
| Shipper email | noreply@your-domain.com — on your verified domain |
| Response email | Optional, e.g. support@your-domain.com |
// In a controller, service or lifecycle hook
await strapi.plugin("email").service("email").send({
to: order.customerEmail,
subject: `Your order #${order.id} is confirmed`,
text: "Thanks! Your order ships tomorrow.",
html: "<p>Thanks! Your order ships tomorrow.</p>",
});In the admin panel open Settings and, under Email plugin, the configuration page. It shows the active provider and has a Send test email button. Then request a password reset for a test user to check the Users & Permissions sender too.
| Error | Cause and fix |
|---|---|
Configuration page still shows sendmail | The config is not under email.config, or Strapi was not restarted. |
| Provider fails to load on startup | @strapi/provider-email-nodemailer is not installed in this project. |
| Test email works, password reset does not | Shipper email in the Users & Permissions templates is still no-reply@strapi.io. |
Invalid login: 535 | Wrong token login or password in .env. |
| Connection timeout | Outbound port blocked. Use 8587 with secure: false or 8465 with secure: true. |
| Mail goes to spam | A From address is not on your verified domain. |
Install @strapi/provider-email-nodemailer, then set the email plugin's provider to nodemailer in config/plugins.js or config/plugins.ts with host, port, secure and auth under providerOptions. Out of the box Strapi uses the sendmail provider, which depends on a local mail server most hosts do not have.
The Users & Permissions plugin keeps its own sender for the Reset password and Email address confirmation templates, and it defaults to no-reply@strapi.io — defaultFrom in config/plugins does not override it. Change Shipper email in both templates to an address on your verified domain, or the relay rejects the message or the recipient marks it as spoofed.
Open Settings in the admin panel and, under Email plugin, the configuration page. It shows the active provider and has a Send test email button. The test uses defaultFrom, so it can pass while Users & Permissions emails still fail on their own sender.
false with port 587 — Nodemailer upgrades the connection with STARTTLS before authenticating. true with port 465, which is TLS from the first byte. The mismatched pairs fail with a TLS error or a timeout.
Call strapi.plugin('email').service('email').send() with to, subject, text and html from a controller, service or lifecycle hook. from and replyTo are optional and fall back to the defaults in config/plugins. Await it inside a try/catch — a failed send throws.
To the URL in Settings → Users & Permissions plugin → Advanced settings → Reset password page. Strapi has no public reset page of its own for end users, so enter the page of your front-end application that accepts the code and sets the new password.