From abbceae2c843649ec58d06b6b573817bac1aea24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Wed, 25 Oct 2023 14:32:46 +0200 Subject: [PATCH] WIP: Add email notifications --- .env | 3 + assets/images/logo.png | Bin 0 -> 7437 bytes assets/mjml/layout.mjml | 101 +++ config/services.yaml | 7 + package-lock.json | 1312 +++++++++++++++++++++++++++++ package.json | 4 +- src/Email/Mailer.php | 97 +++ src/Email/WelcomeEmailMailer.php | 28 + src/Model/EmailAttachmentDto.php | 25 + templates/email/layout.html.twig | 272 ++++++ templates/email/welcome.html.twig | 15 + 11 files changed, 1863 insertions(+), 1 deletion(-) create mode 100644 assets/images/logo.png create mode 100644 assets/mjml/layout.mjml create mode 100644 src/Email/Mailer.php create mode 100644 src/Email/WelcomeEmailMailer.php create mode 100644 src/Model/EmailAttachmentDto.php create mode 100644 templates/email/layout.html.twig create mode 100644 templates/email/welcome.html.twig diff --git a/.env b/.env index 13bb19d..06a1056 100644 --- a/.env +++ b/.env @@ -47,3 +47,6 @@ APP_BPN_ENDPOINT= APP_BPN_CRM_ID_ADMIN=1292 APP_BPN_CRM_ID_MANAGER=1293 APP_BPN_CRM_ID_TEAMER=1070 + +APP_DEFAULT_EMAIL_FROM=info@ep-reisen.de +APP_DEFAULT_EMAIL_TO=info@ep-reisen.de \ No newline at end of file diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1fc85107960fc6ec619d9a63b28b272c5216e677 GIT binary patch literal 7437 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 literal 0 HcmV?d00001 diff --git a/assets/mjml/layout.mjml b/assets/mjml/layout.mjml new file mode 100644 index 0000000..3176b0a --- /dev/null +++ b/assets/mjml/layout.mjml @@ -0,0 +1,101 @@ + + + + MyE&P Team + MyE&P Team + + + + + h1 { + font-weight: bold; + font-size: 32px; + line-height: 36px; + margin-bottom: 0; + padding-bottom: 16px; + } + h2 { + font-weight: normal; + font-size: 24px; + line-height: 28px; + margin-bottom: 0; + } + p { + padding-bottom: 16px; + } + p.small { + font-size: 14px; + color: #999999; + } + a { + text-decoration: underline; + color: #5F7983; + } + a.footerlink { + text-decoration: none; + color: inherit; + } + a.button { + text-decoration: none; + color: white; + display: inline-block; + background-color: #3d8ccb; + padding: 8px 16px; + border-radius: 4px; + } + + + + + + + + + + {% block body %} +

+ Lorem ipsum dolor sit amet +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores + earum eius fugiat in nesciunt quas quidem vitae? +

+

+ Lorem ipsum dolor +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores + earum eius fugiat in nesciunt quas quidem vitae? +

+

+ + Button + +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus, eveniet! +

+ {% endblock %} +
+
+
+ + + + E&P Reisen und Events GmbH +
+ Aachener Str. 326-328 +
+ 50933 Köln +
+
+ + + Impressum + | + Datenschutz + + +
+
+
diff --git a/config/services.yaml b/config/services.yaml index bc6c08a..4602fa1 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -7,6 +7,9 @@ parameters: bpn_crm_id_manager: '%env(int:APP_BPN_CRM_ID_MANAGER)%' bpn_crm_id_teamer: '%env(int:APP_BPN_CRM_ID_TEAMER)%' + default_email_from: '%env(APP_DEFAULT_EMAIL_FROM)%' + default_email_to: '%env(APP_DEFAULT_EMAIL_TO)%' + services: _defaults: autowire: true @@ -108,3 +111,7 @@ services: App\Service\Pdf\InvoiceRenderer: arguments: $options: { 'project_dir': '%kernel.project_dir%' } + + App\Email\Mailer: + arguments: + $defaults: { 'from': '%default_email_from%', 'to': '%default_email_to%' } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8c26bcd..a7bc7d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "dropzone": "^6.0.0-beta.2", "file-loader": "^6.2.0", "flatpickr": "^4.6.13", + "mjml": "^4.14.1", "postcss": "^8.4.29", "postcss-import": "^15.1.0", "postcss-loader": "^7.3.3", @@ -1945,6 +1946,12 @@ "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" } }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -2738,6 +2745,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2849,6 +2862,15 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -3257,6 +3279,16 @@ "node": ">=6" } }, + "node_modules/camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", + "dev": true, + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -3333,6 +3365,189 @@ "node": ">=0.8.0" } }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dev": true, + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio-select/node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio-select/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/cheerio-select/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/cheerio-select/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/cheerio-select/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -3396,6 +3611,18 @@ "node": ">=8" } }, + "node_modules/clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, "node_modules/clean-webpack-plugin": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz", @@ -3411,6 +3638,17 @@ "webpack": ">=4.0.0 <6.0.0" } }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -3524,6 +3762,16 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -4165,6 +4413,90 @@ "just-extend": "^5.0.0" } }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/editorconfig/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4268,6 +4600,18 @@ "node": ">=6" } }, + "node_modules/escape-goat": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", + "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -4732,6 +5076,15 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -4894,6 +5247,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -4952,6 +5314,33 @@ } ] }, + "node_modules/html-minifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", + "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", + "dev": true, + "dependencies": { + "camel-case": "^3.0.0", + "clean-css": "^4.2.1", + "commander": "^2.19.0", + "he": "^1.2.0", + "param-case": "^2.1.1", + "relateurl": "^0.2.7", + "uglify-js": "^3.5.1" + }, + "bin": { + "html-minifier": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-minifier/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -5121,6 +5510,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -5460,6 +5855,66 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-beautify": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz", + "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^8.1.0", + "nopt": "^6.0.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5514,6 +5969,34 @@ "node": ">=6" } }, + "node_modules/juice": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/juice/-/juice-9.1.0.tgz", + "integrity": "sha512-odblShmPrUoHUwRuC8EmLji5bPP2MLO1GL+gt4XU3tT2ECmbSrrMjtMQaqg3wgMFP2zvUzdPZGfxc5Trk3Z+fQ==", + "dev": true, + "dependencies": { + "cheerio": "^1.0.0-rc.12", + "commander": "^6.1.0", + "mensch": "^0.3.4", + "slick": "^1.12.2", + "web-resource-inliner": "^6.0.1" + }, + "bin": { + "juice": "bin/juice" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/juice/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/just-extend": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-5.1.1.tgz", @@ -5631,6 +6114,12 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true }, + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", + "dev": true + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5682,6 +6171,12 @@ "node": ">= 4.0.0" } }, + "node_modules/mensch": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz", + "integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==", + "dev": true + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -5866,6 +6361,491 @@ "node": "*" } }, + "node_modules/mjml": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml/-/mjml-4.14.1.tgz", + "integrity": "sha512-f/wnWWIVbeb/ge3ff7c/KYYizI13QbGIp03odwwkCThsJsacw4gpZZAU7V4gXY3HxSXP2/q3jxOfaHVbkfNpOQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "mjml-cli": "4.14.1", + "mjml-core": "4.14.1", + "mjml-migrate": "4.14.1", + "mjml-preset-core": "4.14.1", + "mjml-validator": "4.13.0" + }, + "bin": { + "mjml": "bin/mjml" + } + }, + "node_modules/mjml-accordion": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.14.1.tgz", + "integrity": "sha512-dpNXyjnhYwhM75JSjD4wFUa9JgHm86M2pa0CoTzdv1zOQz67ilc4BoK5mc2S0gOjJpjBShM5eOJuCyVIuAPC6w==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-body": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.14.1.tgz", + "integrity": "sha512-YpXcK3o2o1U+fhI8f60xahrhXuHmav6BZez9vIN3ZEJOxPFSr+qgr1cT2iyFz50L5+ZsLIVj2ZY+ALQjdsg8ig==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-button": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.14.1.tgz", + "integrity": "sha512-V1Tl1vQ3lXYvvqHJHvGcc8URr7V1l/ZOsv7iLV4QRrh7kjKBXaRS7uUJtz6/PzEbNsGQCiNtXrODqcijLWlgaw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-carousel": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.14.1.tgz", + "integrity": "sha512-Ku3MUWPk/TwHxVgKEUtzspy/ePaWtN/3z6/qvNik0KIn0ZUIZ4zvR2JtaVL5nd30LHSmUaNj30XMPkCjYiKkFA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-cli": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.14.1.tgz", + "integrity": "sha512-Gy6MnSygFXs0U1qOXTHqBg2vZX2VL/fAacgQzD4MHq4OuybWaTNSzXRwxBXYCxT3IJB874n2Q0Mxp+Xka+tnZg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "chokidar": "^3.0.0", + "glob": "^7.1.1", + "html-minifier": "^4.0.0", + "js-beautify": "^1.6.14", + "lodash": "^4.17.21", + "mjml-core": "4.14.1", + "mjml-migrate": "4.14.1", + "mjml-parser-xml": "4.14.1", + "mjml-validator": "4.13.0", + "yargs": "^16.1.0" + }, + "bin": { + "mjml-cli": "bin/mjml" + } + }, + "node_modules/mjml-column": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.14.1.tgz", + "integrity": "sha512-iixVCIX1YJtpQuwG2WbDr7FqofQrlTtGQ4+YAZXGiLThs0En3xNIJFQX9xJ8sgLEGGltyooHiNICBRlzSp9fDg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-core": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.14.1.tgz", + "integrity": "sha512-di88rSfX+8r4r+cEqlQCO7CRM4mYZrfe2wSCu2je38i+ujjkLpF72cgLnjBlSG5aOUCZgYvlsZ85stqIz9LQfA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "cheerio": "1.0.0-rc.12", + "detect-node": "^2.0.4", + "html-minifier": "^4.0.0", + "js-beautify": "^1.6.14", + "juice": "^9.0.0", + "lodash": "^4.17.21", + "mjml-migrate": "4.14.1", + "mjml-parser-xml": "4.14.1", + "mjml-validator": "4.13.0" + } + }, + "node_modules/mjml-divider": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.14.1.tgz", + "integrity": "sha512-agqWY0aW2xaMiUOhYKDvcAAfOLalpbbtjKZAl1vWmNkURaoK4L7MgDilKHSJDFUlHGm2ZOArTrq8i6K0iyThBQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-group": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.14.1.tgz", + "integrity": "sha512-dJt5batgEJ7wxlxzqOfHOI94ABX+8DZBvAlHuddYO4CsLFHYv6XRIArLAMMnAKU76r6p3X8JxYeOjKZXdv49kg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.14.1.tgz", + "integrity": "sha512-KoCbtSeTAhx05Ugn9TB2UYt5sQinSCb7RGRer5iPQ3CrXj8hT5B5Svn6qvf/GACPkWl4auExHQh+XgLB+r3OEA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head-attributes": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.14.1.tgz", + "integrity": "sha512-XdUNOp2csK28kBDSistInOyzWNwmu5HDNr4y1Z7vSQ1PfkmiuS6jWG7jHUjdoMhs27e6Leuyyc6a8gWSpqSWrg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head-breakpoint": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.14.1.tgz", + "integrity": "sha512-Qw9l/W/I5Z9p7I4ShgnEpAL9if4472ejcznbBnp+4Gq+sZoPa7iYoEPsa9UCGutlaCh3N3tIi2qKhl9qD8DFxA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head-font": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.14.1.tgz", + "integrity": "sha512-oBYm1gaOdEMjE5BoZouRRD4lCNZ1jcpz92NR/F7xDyMaKCGN6T/+r4S5dq1gOLm9zWqClRHaECdFJNEmrDpZqA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head-html-attributes": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head-html-attributes/-/mjml-head-html-attributes-4.14.1.tgz", + "integrity": "sha512-vlJsJc1Sm4Ml2XvLmp01zsdmWmzm6+jNCO7X3eYi9ngEh8LjMCLIQOncnOgjqm9uGpQu2EgUhwvYFZP2luJOVg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head-preview": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.14.1.tgz", + "integrity": "sha512-89gQtt3fhl2dkYpHLF5HDQXz/RLpzecU6wmAIT7Dz6etjLGE1dgq2Ay6Bu/OeHjDcT1gbM131zvBwuXw8OydNw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head-style": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.14.1.tgz", + "integrity": "sha512-XryOuf32EDuUCBT2k99C1+H87IOM919oY6IqxKFJCDkmsbywKIum7ibhweJdcxiYGONKTC6xjuibGD3fQTTYNQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-head-title": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.14.1.tgz", + "integrity": "sha512-aIfpmlQdf1eJZSSrFodmlC4g5GudBti2eMyG42M7/3NeLM6anEWoe+UkF/6OG4Zy0tCQ40BDJ5iBZlMsjQICzw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-hero": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.14.1.tgz", + "integrity": "sha512-TQJ3yfjrKYGkdEWjHLHhL99u/meKFYgnfJvlo9xeBvRjSM696jIjdqaPHaunfw4CP6d2OpCIMuacgOsvqQMWOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-image": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.14.1.tgz", + "integrity": "sha512-jfKLPHXuFq83okwlNM1Um/AEWeVDgs2JXIOsWp2TtvXosnRvGGMzA5stKLYdy1x6UfKF4c1ovpMS162aYGp+xQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-migrate": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.14.1.tgz", + "integrity": "sha512-d+9HKQOhZi3ZFAaFSDdjzJX9eDQGjMf3BArLWNm2okC4ZgfJSpOc77kgCyFV8ugvwc8fFegPnSV60Jl4xtvK2A==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "js-beautify": "^1.6.14", + "lodash": "^4.17.21", + "mjml-core": "4.14.1", + "mjml-parser-xml": "4.14.1", + "yargs": "^16.1.0" + }, + "bin": { + "migrate": "lib/cli.js" + } + }, + "node_modules/mjml-navbar": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.14.1.tgz", + "integrity": "sha512-rNy1Kw8CR3WQ+M55PFBAUDz2VEOjz+sk06OFnsnmNjoMVCjo1EV7OFLDAkmxAwqkC8h4zQWEOFY0MBqqoAg7+A==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-parser-xml": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.14.1.tgz", + "integrity": "sha512-9WQVeukbXfq9DUcZ8wOsHC6BTdhaVwTAJDYMIQglXLwKwN7I4pTCguDDHy5d0kbbzK5OCVxCdZe+bfVI6XANOQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "detect-node": "2.0.4", + "htmlparser2": "^8.0.1", + "lodash": "^4.17.15" + } + }, + "node_modules/mjml-parser-xml/node_modules/detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "node_modules/mjml-parser-xml/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/mjml-parser-xml/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/mjml-parser-xml/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/mjml-parser-xml/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/mjml-parser-xml/node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/mjml-preset-core": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-preset-core/-/mjml-preset-core-4.14.1.tgz", + "integrity": "sha512-uUCqK9Z9d39rwB/+JDV2KWSZGB46W7rPQpc9Xnw1DRP7wD7qAfJwK6AZFCwfTgWdSxw0PwquVNcrUS9yBa9uhw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "mjml-accordion": "4.14.1", + "mjml-body": "4.14.1", + "mjml-button": "4.14.1", + "mjml-carousel": "4.14.1", + "mjml-column": "4.14.1", + "mjml-divider": "4.14.1", + "mjml-group": "4.14.1", + "mjml-head": "4.14.1", + "mjml-head-attributes": "4.14.1", + "mjml-head-breakpoint": "4.14.1", + "mjml-head-font": "4.14.1", + "mjml-head-html-attributes": "4.14.1", + "mjml-head-preview": "4.14.1", + "mjml-head-style": "4.14.1", + "mjml-head-title": "4.14.1", + "mjml-hero": "4.14.1", + "mjml-image": "4.14.1", + "mjml-navbar": "4.14.1", + "mjml-raw": "4.14.1", + "mjml-section": "4.14.1", + "mjml-social": "4.14.1", + "mjml-spacer": "4.14.1", + "mjml-table": "4.14.1", + "mjml-text": "4.14.1", + "mjml-wrapper": "4.14.1" + } + }, + "node_modules/mjml-raw": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.14.1.tgz", + "integrity": "sha512-9+4wzoXnCtfV6QPmjfJkZ50hxFB4Z8QZnl2Ac0D1Cn3dUF46UkmO5NLMu7UDIlm5DdFyycZrMOwvZS4wv9ksPw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-section": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.14.1.tgz", + "integrity": "sha512-Ik5pTUhpT3DOfB3hEmAWp8rZ0ilWtIivnL8XdUJRfgYE9D+MCRn+reIO+DAoJHxiQoI6gyeKkIP4B9OrQ7cHQw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-social": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.14.1.tgz", + "integrity": "sha512-G44aOZXgZHukirjkeQWTTV36UywtE2YvSwWGNfo/8d+k5JdJJhCIrlwaahyKEAyH63G1B0Zt8b2lEWx0jigYUw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-spacer": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.14.1.tgz", + "integrity": "sha512-5SfQCXTd3JBgRH1pUy6NVZ0lXBiRqFJPVHBdtC3OFvUS3q1w16eaAXlIUWMKTfy8CKhQrCiE6m65kc662ZpYxA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-table": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.14.1.tgz", + "integrity": "sha512-aVBdX3WpyKVGh/PZNn2KgRem+PQhWlvnD00DKxDejRBsBSKYSwZ0t3EfFvZOoJ9DzfHsN0dHuwd6Z18Ps44NFQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-text": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.14.1.tgz", + "integrity": "sha512-yZuvf5z6qUxEo5CqOhCUltJlR6oySKVcQNHwoV5sneMaKdmBiaU4VDnlYFera9gMD9o3KBHIX6kUg7EHnCwBRQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1" + } + }, + "node_modules/mjml-validator": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.13.0.tgz", + "integrity": "sha512-uURYfyQYtHJ6Qz/1A7/+E9ezfcoISoLZhYK3olsxKRViwaA2Mm8gy/J3yggZXnsUXWUns7Qymycm5LglLEIiQg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6" + } + }, + "node_modules/mjml-wrapper": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.14.1.tgz", + "integrity": "sha512-aA5Xlq6d0hZ5LY+RvSaBqmVcLkvPvdhyAv3vQf3G41Gfhel4oIPmkLnVpHselWhV14A0KwIOIAKVxHtSAxyOTQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "lodash": "^4.17.21", + "mjml-core": "4.14.1", + "mjml-section": "4.14.1" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5929,6 +6909,35 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "dependencies": { + "lower-case": "^1.1.1" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -5944,6 +6953,21 @@ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6139,6 +7163,15 @@ "node": ">=6" } }, + "node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", + "dev": true, + "dependencies": { + "no-case": "^2.2.0" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6169,6 +7202,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dev": true, + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -7036,6 +8121,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -7277,6 +8368,15 @@ "jsesc": "bin/jsesc" } }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -7290,6 +8390,15 @@ "strip-ansi": "^6.0.1" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -7714,6 +8823,15 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/slick": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz", + "integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -8341,6 +9459,12 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -8360,6 +9484,18 @@ "node": ">= 0.6" } }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/undici-types": { "version": "5.25.3", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", @@ -8445,6 +9581,12 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", + "dev": true + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -8484,6 +9626,15 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/valid-data-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz", + "integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -8515,6 +9666,71 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/web-resource-inliner": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz", + "integrity": "sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "escape-goat": "^3.0.0", + "htmlparser2": "^5.0.0", + "mime": "^2.4.6", + "node-fetch": "^2.6.0", + "valid-data-url": "^3.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/web-resource-inliner/node_modules/domhandler": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", + "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/web-resource-inliner/node_modules/htmlparser2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz", + "integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^3.3.0", + "domutils": "^2.4.2", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/fb55/htmlparser2?sponsor=1" + } + }, + "node_modules/web-resource-inliner/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, "node_modules/webpack": { "version": "5.89.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", @@ -8858,6 +10074,16 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8879,6 +10105,56 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8906,6 +10182,15 @@ } } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -8921,6 +10206,24 @@ "node": ">= 14" } }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", @@ -8929,6 +10232,15 @@ "engines": { "node": ">=12" } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } } } } diff --git a/package.json b/package.json index 07ae7bd..e6de70b 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dropzone": "^6.0.0-beta.2", "file-loader": "^6.2.0", "flatpickr": "^4.6.13", + "mjml": "^4.14.1", "postcss": "^8.4.29", "postcss-import": "^15.1.0", "postcss-loader": "^7.3.3", @@ -31,7 +32,8 @@ "dev-server": "encore dev-server", "dev": "encore dev", "watch": "encore dev --watch", - "build": "encore production --progress" + "build": "encore production --progress", + "mjml": "mjml assets/mjml/layout.mjml -o templates/email/layout.html.twig" }, "dependencies": { "sortablejs": "^1.15.0" diff --git a/src/Email/Mailer.php b/src/Email/Mailer.php new file mode 100644 index 0000000..e4b4d06 --- /dev/null +++ b/src/Email/Mailer.php @@ -0,0 +1,97 @@ +resolveConfig($options); + $email = $this->create($context, $config); + + $recipients = (array) $config['to']; + + foreach ($recipients as $recipient) { + $email->to($recipient); + $this->send($email); + } + } + + public function create(array $context, array $config): TemplatedEmail + { + $email = (new TemplatedEmail()) + ->from($config['from']) + ->subject($this->translator->trans($config['subject'], $config['subject_parameters'])) + ->htmlTemplate($config['template']) + ->context($context) + ; + + foreach ($config['attachments'] as $attachment) { + /* @var EmailAttachmentDto $attachment */ + $email->attach($attachment->getContent(), $attachment->getName(), $attachment->getMimeType()); + } + + return $email; + } + + public function send(TemplatedEmail $email): void + { + $recipients = array_map(fn (Address $address) => $address->toString(), $email->getTo()); + + try { + $this->mailer->send($email); + $this->logger->info('Send email', [ + 'to' => $recipients, + 'subject' => $email->getSubject(), + ]); + } catch (TransportExceptionInterface $e) { + $this->logger->error('Email could not be sent', [ + 'to' => $recipients, + 'subject' => $email->getSubject(), + 'error' => $e->getMessage(), + ]); + } + } + + private function resolveConfig(array $options): array + { + $resolver = new OptionsResolver(); + + $resolver + ->setDefaults([ + 'from' => $this->defaults['from'], + 'to' => $this->defaults['to'], + 'subject_parameters' => [], + 'attachments' => [], + ]) + ->setRequired([ + 'template', + 'subject', + ]) + ->setAllowedTypes('to', ['string', 'array']) + ->setAllowedTypes('template', 'string') + ->setAllowedTypes('subject', 'string') + ->setAllowedTypes('subject_parameters', 'array') + ->setAllowedTypes('attachments', 'array') + ; + + return $resolver->resolve($options); + } +} diff --git a/src/Email/WelcomeEmailMailer.php b/src/Email/WelcomeEmailMailer.php new file mode 100644 index 0000000..62d61b9 --- /dev/null +++ b/src/Email/WelcomeEmailMailer.php @@ -0,0 +1,28 @@ +mailer->createAndSendEmail([ + 'user' => $user, + ], [ + 'to' => $user->getEmail(), + 'subject' => 'Willkommen bei MyE&P Team', + 'template' => 'email/welcome.html.twig', + ]); + + $this->logger->info('Send welcome email', [ + 'user_id' => $user->getId(), + 'user_email' => $user->getEmail(), + ]); + } +} diff --git a/src/Model/EmailAttachmentDto.php b/src/Model/EmailAttachmentDto.php new file mode 100644 index 0000000..2766385 --- /dev/null +++ b/src/Model/EmailAttachmentDto.php @@ -0,0 +1,25 @@ +name; + } + + public function getContent(): string + { + return $this->content; + } + + public function getMimeType(): string + { + return $this->mimeType; + } +} diff --git a/templates/email/layout.html.twig b/templates/email/layout.html.twig new file mode 100644 index 0000000..2ac3813 --- /dev/null +++ b/templates/email/layout.html.twig @@ -0,0 +1,272 @@ + + + + + MyE&P Team + + + + + + + + + + + + + + + + + + + +
MyE&P Team
+
+ +
+ + + + + + +
+ + +
+ + + + + + +
+ + + + + + +
+ + + + + + +
+ Logo E&P +
+
+
+
+ +
+
+
+ +
+ + + + + + +
+ +
+ + + + + + +
+
{% block body %}

Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores earum eius fugiat in nesciunt quas quidem vitae?

+

Lorem ipsum dolor

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores earum eius fugiat in nesciunt quas quidem vitae?

+

+ Button +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus, eveniet!

{% endblock %} +
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + + + + + +
+
E&P Reisen und Events GmbH
Aachener Str. 326-328
50933 Köln
+
+
+ +
+ + + + + + +
+ +
+
+ +
+
+ +
+ + + diff --git a/templates/email/welcome.html.twig b/templates/email/welcome.html.twig new file mode 100644 index 0000000..274f33e --- /dev/null +++ b/templates/email/welcome.html.twig @@ -0,0 +1,15 @@ +{% extends 'email/layout.html.twig' %} + +{% block body %} +

+ Willkommen bei MyE&P Team +

+

+ Hallo {{ user.firstName }}, +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid asperiores atque, commodi deleniti + dignissimos dolorum earum ex facere facilis necessitatibus non omnis pariatur possimus quas repudiandae sit + soluta tenetur, voluptatem. +

+{% endblock %} \ No newline at end of file