{"id":20773557,"url":"https://github.com/baybreezy/strapi-plugin-email-designer-5","last_synced_at":"2025-04-30T15:07:35.373Z","repository":{"id":257804949,"uuid":"865134087","full_name":"BayBreezy/strapi-plugin-email-designer-5","owner":"BayBreezy","description":"Design your own email templates directly from the Strapi admin panel and use the magic to send programmatically email from your controllers / services.","archived":false,"fork":false,"pushed_at":"2025-02-10T17:10:04.000Z","size":1912,"stargazers_count":19,"open_issues_count":9,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-30T17:11:21.203Z","etag":null,"topics":["email-designer","strapi-plugin","strapi5","unlayer"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/strapi-plugin-email-designer-5","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BayBreezy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-09-30T03:16:10.000Z","updated_at":"2025-03-19T15:16:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"26141196-f9bb-4bf2-b8c5-29bcc12971a9","html_url":"https://github.com/BayBreezy/strapi-plugin-email-designer-5","commit_stats":null,"previous_names":["baybreezy/strapi-plugin-email-designer-5"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BayBreezy%2Fstrapi-plugin-email-designer-5","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BayBreezy%2Fstrapi-plugin-email-designer-5/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BayBreezy%2Fstrapi-plugin-email-designer-5/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BayBreezy%2Fstrapi-plugin-email-designer-5/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BayBreezy","download_url":"https://codeload.github.com/BayBreezy/strapi-plugin-email-designer-5/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251727999,"owners_count":21634129,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email-designer","strapi-plugin","strapi5","unlayer"],"created_at":"2024-11-17T12:26:13.233Z","updated_at":"2025-04-30T15:07:35.346Z","avatar_url":"https://github.com/BayBreezy.png","language":"TypeScript","funding_links":["https://buymeacoffee.com/llehXIrI8g"],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"/Email Designer Logo.jpg\" style=\"height: 70px; margin: 0px; border-radius: 12px;\" /\u003e\n\n# \u003cimg src=\"/Email Designer Logo.jpg\" style=\"height: 26px; margin: 0px; border-radius: 4px;\" /\u003e Strapi Email Designer (v5)\n\nDesign your own email templates directly from the Strapi admin panel and use the magic to send programmatically email from your controllers / services.\n\n![Screenshot of an imported design](./imgs/design.jpeg)\n\n- [ Strapi Email Designer (v5)](#-strapi-email-designer-v5)\n  - [❤️ Credits](#️-credits)\n  - [💸 Support Me](#-support-me)\n  - [⚙️ Version](#️-version)\n  - [✅ Prerequisites](#-prerequisites)\n  - [⬇️ Installation](#️-installation)\n  - [🎚️ Middleware Configuration](#️-middleware-configuration)\n  - [🎚️ Plugin Configuration](#️-plugin-configuration)\n    - [📧 Nodemailer](#-nodemailer)\n    - [⚙️ Default configuration](#️-default-configuration)\n  - [▶️ Usage](#️-usage)\n    - [✅ Creating a new design](#-creating-a-new-design)\n    - [✅ Importing a design](#-importing-a-design)\n    - [✅ Exporting a design](#-exporting-a-design)\n    - [✅ Importing a Single Design](#-importing-a-single-design)\n    - [✅ Saving a design](#-saving-a-design)\n  - [{ } Mustache](#--mustache)\n  - [💻 Programmatically Sending Emails](#-programmatically-sending-emails)\n  - [🚀 Available Services](#-available-services)\n    - [✅ Email Services](#-email-services)\n      - [`sendTemplatedEmail`](#sendtemplatedemail)\n      - [`compose`](#compose)\n  - [🛟 Contributing](#-contributing)\n  - [✍🏽 License](#-license)\n  - [🎆 Images](#-images)\n\n## ❤️ Credits\n\nSpecial thanks to:\n\n- [Unlayer](https://unlayer.com/) for the amazing email editor\n- [Strapi Plugin Email Designer](https://github.com/alexzaganelli/strapi-plugin-email-designer) for doing the heavy lifting for v3 and v4\n\n## 💸 Support Me\n\nIf you can 😊\n\n\u003ca href=\"https://buymeacoffee.com/llehXIrI8g\" target=\"_blank\"\u003e\u003cimg src=\"https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\" alt=\"Buy Me A Coffee\" style=\"height: 41px !important;width: 174px !important\" \u003e\u003c/a\u003e\n\n## ⚙️ Version\n\nThis plugin is compatible with Strapi v5.\n\nHow plugins are structured in v5 is way different than v4, so I am not trying to make this plugin compatible with v4. Use the [Email Designer plugin here](https://github.com/alexzaganelli/strapi-plugin-email-designer) for v4.\n\n## ✅ Prerequisites\n\n- Node v18+ (I recommend using [nvm](https://github.com/nvm-sh/nvm), there is a windows and mac/linux version)\n- A Strapi v5 project (`npx create-strapi-app@latest my-project`)\n\n## ⬇️ Installation\n\nInstall the plugin by runnig the following command:\n\n```bash\nnpm install strapi-plugin-email-designer-5\n```\n\n## 🎚️ Middleware Configuration\n\nBy default, Strapi's security is tight. You will need to add the following to your `config/middleware.ts` file:\n\n```ts\n{\n  name: \"strapi::security\",\n  config: {\n    contentSecurityPolicy: {\n      useDefaults: true,\n      directives: {\n        \"script-src\": [\"'self'\", \"'unsafe-inline'\", \"editor.unlayer.com\"],\n        \"frame-src\": [\"'self'\", \"editor.unlayer.com\"],\n        upgradeInsecureRequests: null,\n      },\n    },\n  },\n}\n```\n\nEnsure that you replace the `\"strapi::security\"` line in the file with the above.\n\n## 🎚️ Plugin Configuration\n\nThe plugin configuration accepts most of the properties that can be passed to the Unlayer editor. You can get more information about them here: https://docs.unlayer.com/docs/getting-started#configuration-options\n\nThis is the type definition for the configuration:\n\n```ts\nimport type { EmailEditorProps } from \"react-email-editor\";\n\nexport type EmailConfig = Pick\u003c\n  NonNullable\u003cEmailEditorProps[\"options\"]\u003e,\n  | \"projectId\"\n  | \"locale\"\n  | \"appearance\"\n  | \"user\"\n  | \"mergeTags\"\n  | \"designTags\"\n  | \"specialLinks\"\n  | \"tools\"\n  | \"blocks\"\n  | \"fonts\"\n  | \"safeHtml\"\n  | \"customCSS\"\n  | \"customJS\"\n  | \"textDirection\"\n\u003e;\n```\n\n### 📧 Nodemailer\n\nIf you are going to send emails from the Strapi backend, you need to configure the email plugin. You can visit the docs [here](https://github.com/strapi/strapi/tree/main/packages/providers/email-nodemailer) to learn more\n\n```bash\nnpm install @strapi/provider-email-nodemailer --save\n```\n\n### ⚙️ Default configuration\n\nSome options are passed by default to the editor. Expand the following object to see the default configuration:\n\n\u003cdetails\u003e\n\u003csummary style=\"font-weight: bold\"\u003eDefault configuration\u003c/summary\u003e\n\n```ts\n{\n  mergeTagsConfig: {\n    autocompleteTriggerChar: \"@\",\n    sort: false,\n    delimiter: [\"{{\", \"}}\"],\n  },\n  appearance: {\n    theme: \"modern_light\",\n  },\n  fonts: {\n    showDefaultFonts: false,\n  },\n  tools: {\n    image: {\n      properties: {\n        src: {\n          value: {\n            url: \"https://picsum.photos/600/350\",\n          },\n        },\n      },\n    },\n  },\n  mergeTags: {\n    core: {\n      name: \"Core\",\n      mergeTags: {\n        // Values that can be used in the Reset Password context\n        resetPassword: {\n          name: \"Reset Password\",\n          mergeTags: {\n            // User in the Reset Password context\n            user: {\n              name: \"USER\",\n              mergeTags: {\n                username: {\n                  name: \"Username\",\n                  value: \"{{= USER.username }}\",\n                  sample: \"john_doe\",\n                },\n                email: {\n                  name: \"Email\",\n                  value: \"{{= USER.email }}\",\n                  sample: \"johndoe@example.com\",\n                },\n              },\n            },\n            token: {\n              name: \"TOKEN\",\n              value: \"{{= TOKEN }}\",\n              sample: \"corresponds-to-the-token-generated-to-be-able-to-reset-the-password\",\n            },\n            url: {\n              name: \"URL\",\n              value: \"{{= URL }}\",\n              sample: \"is-the-link-where-the-user-will-be-redirected-after-clicking-on-it-in-the-email\",\n            },\n            serverUrl: {\n              name: \"SERVER_URL\",\n              value: \"{{= SERVER_URL }}\",\n              sample: \"is-the-absolute-server-url-(configured-in-server-configuration)\",\n            },\n          },\n        },\n        // Values that can be used in the Email Addres Confirmation context\n        addressConfirmation: {\n          name: \"Confirm Address\",\n          mergeTags: {\n            // User in the Email Address Confirmation context\n            user: {\n              name: \"USER\",\n              mergeTags: {\n                username: {\n                  name: \"Username\",\n                  value: \"{{= USER.username }}\",\n                  sample: \"john_doe\",\n                },\n                email: {\n                  name: \"Email\",\n                  value: \"{{= USER.email }}\",\n                  sample: \"johndoe@example.com\",\n                },\n              },\n            },\n            code: {\n              name: \"CODE\",\n              value: \"{{= CODE }}\",\n              sample: \"corresponds-to-the-CODE-generated-to-be-able-confirm-the-user-email\",\n            },\n            url: {\n              name: \"URL\",\n              value: \"{{= URL }}\",\n              sample:\n                \"is-the-Strapi-backend-URL-that-confirms-the-code-(by-default-/auth/email-confirmation)\",\n            },\n            serverUrl: {\n              name: \"SERVER_URL\",\n              value: \"{{= SERVER_URL }}\",\n              sample: \"is-the-absolute-server-url-(configured-in-server-configuration)\",\n            },\n          },\n        },\n      },\n    },\n    mustache: {\n      name: \"Mustache\",\n      mergeTags: {\n        basic: {\n          name: \"Basic Output\",\n          mergeTags: {\n            raw: {\n              name: \"Display Raw Content\",\n              value: \"{{{REPLACE_ME}}}\",\n            },\n            output: {\n              name: \"Regular Output\",\n              value: \"{{REPLACE_ME}}\",\n            },\n            dottedOutput: {\n              name: \"Dot notation for Output\",\n              value: \"{{REPLACE_ME.NESTED_VALUE}}\",\n            },\n          },\n        },\n        loops: {\n          name: \"Loops\",\n          mergeTags: {\n            raw: {\n              name: \"Display Raw Content in Loop\",\n              value: \"{{#ARRAY_OR_OBJECT_TO_ITERATE}}\\n{{{REPLACE_ME}}}\\n{{/ARRAY_OR_OBJECT_TO_ITERATE}}\",\n            },\n            output: {\n              name: \"Regular Output in Loop\",\n              value: \"{{#ARRAY_OR_OBJECT_TO_ITERATE}}\\n{{REPLACE_ME}}\\n{{/ARRAY_OR_OBJECT_TO_ITERATE}}\",\n            },\n            dottedOutput: {\n              name: \"Dot notation for Output in Loop\",\n              value:\n                \"{{#ARRAY_OR_OBJECT_TO_ITERATE}}\\n{{REPLACE_ME.NESTED_VALUE}}\\n{{/ARRAY_OR_OBJECT_TO_ITERATE}}\",\n            },\n          },\n        },\n      },\n    },\n  },\n}\n```\n\n\u003c/details\u003e\n\n\u003cbr/\u003e\n\nIf you wish to pass in any configuration, you can do so in the `config/plugins.ts` file. Here is an example of how to pass in a custom configuration:\n\n```ts\n// You can import the EmailConfig type from the plugin\nimport type { EmailConfig } from \"strapi-plugin-email-designer-5/dist/server/src\";\n\nexport default ({ env }) =\u003e ({\n  // You need Email configured if you are gonna send emails from the Strapi backend\n  // This is a simple configuration for development using MailDev\n  email: {\n    config: {\n      provider: \"nodemailer\",\n      providerOptions: {\n        host: \"0.0.0.0\",\n        port: 1025,\n        ignoreTLS: true,\n      },\n    },\n  },\n  // This is the configuration for the Email Designer plugin\n  \"email-designer-5\": {\n    enabled: true,\n    // Your custom configuration here\n    config: {\n      // Here the Merge Tags defined will be merged with the defaults above\n      mergeTags: {\n        company: {\n          name: \"Company\",\n          mergeTags: {\n            name: {\n              name: \"Company Name\",\n              value: \"ACME Corp\",\n              sample: \"ACME Corp\",\n            },\n          },\n        },\n      },\n    } as EmailConfig,\n  },\n});\n```\n\n## ▶️ Usage\n\nAfter installing \u0026 configuring your app for the plugin, you can access the email designer by navigating to the `Email Designer (v5)` section in the admin panel.\n\n![Admin Area](./imgs/custom.png)\n\n### ✅ Creating a new design\n\nClick on the `Create a new email` button to start a new design.\n\n### ✅ Importing a design\n\nYou can import a set of designs that were exported by the platform by clicking on the `Import Email Templates` button located at the bottom right of the page.\n\n### ✅ Exporting a design\n\nYou can export all your designs by clicking the `Export Email Templates` button located at the bottom right of the page.\n\n### ✅ Importing a Single Design\n\nWhen you start a new design, a button will be located in the top right called `Import` that allows you to import a single design. If the json file is valid Unlayer exported design, it will be imported into the editor.\n\n### ✅ Saving a design\n\nOnce you are done editing your design, you can click on the `Save` button located at the top right of the page. The `Template Reference ID`, `Template Name`, \u0026 `Subject` fields are required to save the design.(Well not the last two lol)\n\nThe `Template Reference ID` is a unique identifier for the design. It is used to reference the design when sending emails programmatically.\n\n## { } Mustache\n\nThe backend uses Mustache to render the templates. You can visit the [Mustache documentation](https://mustache.github.io/mustache.5.html) to learn more about how to use it.\n\n## 💻 Programmatically Sending Emails\n\nYou can send emails programmatically by using the `email-designer-5` plugin. Here is an example of how to send an email:\n\n\u003e [!IMPORTANT]  \n\u003e This is tested the `index.ts` file of the `src` folder of my strapi project.\n\n```ts\n// import type { Core } from '@strapi/strapi';\n\nexport default {\n  /**\n   * An asynchronous register function that runs before\n   * your application is initialized.\n   *\n   * This gives you an opportunity to extend code.\n   */\n  register(/* { strapi }: { strapi: Core.Strapi } */) {},\n\n  /**\n   * An asynchronous bootstrap function that runs before\n   * your application gets started.\n   *\n   * This gives you an opportunity to set up your data model,\n   * run jobs, or perform some special logic.\n   */\n  async bootstrap(/* { strapi }: { strapi: Core.Strapi } */) {\n    try {\n      await strapi\n        .plugin(\"email-designer-5\")\n        .service(\"email\")\n        .sendTemplatedEmail(\n          {\n            // required\n            // This can also be an array of email addresses\n            to: \"to@example.com\",\n            // Optional\n            cc: [\"zez@jakce.ad\", \"ilez@gevcanuso.la\"],\n            // Optional\n            bcc: [\"fud@darfuv.py\"],\n            // optional if /config/plugins.js -\u003e email.settings.defaultFrom is set\n            from: \"from@example.com\",\n            // optional if /config/plugins.js -\u003e email.settings.defaultReplyTo is set\n            replyTo: \"reply@example.com\",\n            // optional array of files\n            attachments: [],\n          },\n          {\n            // required - Ref ID defined in the template designer (won't change on import)\n            templateReferenceId: 20,\n            // If provided here will override the template's subject.\n            // Can include variables like `Thank you for your order {{= USER.firstName }}!`\n            subject: `Thank you for your order`,\n          },\n          {\n            // this object must include all variables you're using in your email template\n            USER: { firstName: \"John\", lastName: \"Doe\" },\n            order: {\n              products: [\n                { name: \"Article 1\", price: 9.99 },\n                { name: \"Article 2\", price: 5.55 },\n              ],\n            },\n            shippingCost: 5,\n            total: 20.54,\n          }\n        );\n      strapi.log.info(\"Email sent\");\n    } catch (error) {\n      strapi.log.error(error);\n    }\n  },\n};\n```\n\nThis is what the email looked like in the MailDev client\n\n![MailDev Test Results](./imgs/test-results.jpeg)\n\n## 🚀 Available Services\n\nHere is a list of the services that the plugin provides. You can call upon them in your controllers or services(or wherever you want).\n\n### ✅ Email Services\n\n#### `sendTemplatedEmail`\n\nYou will probably use this one a lot.\n\n```ts\nawait strapi\n  .plugin(\"email-designer-5\")\n  .service(\"email\")\n  .sendTemplatedEmail(EMAIL_OPTIONS_OBJECT, EMAIL_TEMPLATE_OBJECT, DATA);\n```\n\n#### `compose`\n\nI didn't get why this service was deprecated in the original plugin, but i found it useful for sending PDF data to my frontend.\n\n```ts\nawait strapi.plugin(\"email-designer-5\").service(\"email\").compose({ templateReferenceId, data });\n```\n\nThis returns the email HTML and Text with the data merged.\n\n```ts\n{\n  html: \"\u003chtml\u003e...\u003c/html\u003e\",\n  text: \"...\"\n}\n```\n\n## 🛟 Contributing\n\nI am SUPER new to React. I have been using Nuxt all my life. If you see where I could have done something better in the admin area, please let me know. I am open to suggestions.\n\nJust fork the repo, make your changes, and submit a PR. I will review it as soon as I can. I am open to learning new things.\n\n## ✍🏽 License\n\nMIT\n\nI mean, I am not the original author of the plugin. I just made it compatible with Strapi v5. So, I am not sure if I can license it. But, I will keep it MIT for now.\n\n## 🎆 Images\n\nImage of the Core Tab in the Admin UI\n\n![Image of the Core Tab in the Admin UI](imgs/core.png)\n\nImage of the Custom Email Tab in the Admin UI\n\n![Image of the Custom Email Tab in the Admin UI](imgs/custom.png)\n\nImage of the Editor wit imported design\n\n![Image of the Editor wit imported design](imgs/design.jpeg)\n\nImage of Email in MailDev\n\n![Image of Email in MailDev](imgs/test-results.jpeg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaybreezy%2Fstrapi-plugin-email-designer-5","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbaybreezy%2Fstrapi-plugin-email-designer-5","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaybreezy%2Fstrapi-plugin-email-designer-5/lists"}