Edit Email Template (Admin Panel)

Hi Guys, I have a simple question:
where can I edit the email templates for my Strapi Admin panel, e.g .: “Reset Password”?
I mean, the email that the admin gets via “… / admin / auth / forgot-password” is not what I set in “Users & Permissions Plugin> E-Mail templates”. :thinking:

Thanks a lot in advance!

Take a look here:

1 Like

@sunnyson Thank you for the fast answer!
As in the documentation I added my e-mail template to “server.js”. I have two more questions:

  1. On Heroku the domain in the url is wrong, but on localhost it is correct.
  2. How can I get the token? <%= token %> or <%= TOKEN %> unfortunately did not work.


What url do you get on heroku?

@sunnyson http://732b836b-4c9d-4938-a4cc-435024d81c89:56659/admin/reset-password?code=
Something like a UUID, but does not work.

Thats the heroku’s internal UID. That happens because you didn’t configured the Public Url of your app. So strapi gets the host and port instead.

Take a look here:
At the url option.
It should be added to inside the ./config/server.js file

1 Like

Thank you very much, it works. :+1: I thought that only the admin path should be entered in “url”… :blush:

No, the admin path has its own url property inside the admin object.


module.exports = ({ env }) => ({
    url: 'https://myPublicUrl.com', // your public URL, will be used for Auth providers/Email templates that contain the URL template string.
    admin: {
        url: '/dashboard' // defines the path for admin panel, in this case will be accessible at https://myPublicUrl.com/dashboard

All modifications made to the url and admin.url properties require admin rebuild.

1 Like

Woaw, thank you again! :+1: :+1: :+1: Now I finally got it right! :tada:

1 Like

For anyone trying to amend the reset password and email confirmation email template in version 4.

in the extensions folder (if it wasn’t automatically generated just create it in the app route- src/extensions)
then add users-permissions/content-types/user/schema.json, and users-permissions/strapi-server.js.
add the code from below.
this is from the docs -

module.exports = (plugin) => {
  plugin.controllers.auth.forgotPassword = (ctx) => {

module.exports = (plugin) => {
  plugin.controllers.auth.register = (ctx) => {

  return plugin;

the above code will override the node modules, You can copy the code from the node modules do not change anything except the settings.message which is the template.

this is my code

const forgot = require("./email-template/forgot_password");
const reset = require("./email-template/reset_password");

const crypto = require("crypto");
const _ = require("lodash");
const utils = require("@strapi/utils");

const { sanitize } = utils;
const { ApplicationError, ValidationError } = utils.errors;

const emailRegExp =

const sanitizeUser = (user, ctx) => {
  const { auth } = ctx.state;
  const userSchema = strapi.getModel("plugin::users-permissions.user");

  return sanitize.contentAPI.output(user, userSchema, { auth });

const getService = (name) => {
  return strapi.plugin("users-permissions").service(name);
module.exports = (plugin) => {
  plugin.controllers.user.find = (ctx) => {
    console.log(ctx, "I am the find ctx");

  plugin.controllers.auth.forgotPassword = async (ctx) => {
    let { email } = ctx.request.body;

    // Check if the provided email is valid or not.
    const isEmail = emailRegExp.test(email);

    if (isEmail) {
      email = email.toLowerCase();
    } else {
      throw new ValidationError("Please provide a valid email address");

    const pluginStore = await strapi.store({
      type: "plugin",
      name: "users-permissions",

    // Find the user by email.
    const user = await strapi
      .findOne({ where: { email: email.toLowerCase() } });

    // User not found.
    if (!user) {
      throw new ApplicationError("This email does not exist");

    // User blocked
    if (user.blocked) {
      throw new ApplicationError("This user is disabled");

    // Generate random token.
    const resetPasswordToken = crypto.randomBytes(64).toString("hex");

    const settings = await pluginStore
      .get({ key: "email" })
      .then((storeEmail) => {
        try {
          return storeEmail["reset_password"].options;
        } catch (error) {
          return {};

    const advanced = await pluginStore.get({
      key: "advanced",

    const userInfo = await sanitizeUser(user, ctx);


    settings.message = reset.html

    settings.message = await getService("users-permissions").template(
        URL: advanced.email_reset_password,
        USER: userInfo,
        TOKEN: resetPasswordToken,

    settings.object = await getService("users-permissions").template(
        USER: userInfo,

    try {
      // Send an email to the user.
      await strapi
          to: user.email,
            settings.from.email || settings.from.name
              ? `${settings.from.name} <${settings.from.email}>`
              : undefined,
          replyTo: settings.response_email,
          subject: settings.object,
          text: settings.message,
          html: settings.message,
    } catch (err) {
      throw new ApplicationError(err.message);

    // Update the user.
    await strapi
      .update({ where: { id: user.id }, data: { resetPasswordToken } });

    ctx.send({ ok: true });
    console.log(email, "I am the forgot password ctx");

  return plugin;

the node modules path is node_modules/@strapi/plugins-users-permissions/server/controllers/auth.js

I have not done it myself but I believe you could create a controllers folder in extensions folder and just register the controllers in strapi-server.js for better abstraction.

i hope this helps I have been struggling for while until I worked it out.