From fbd6e395a43941c057ac0ba8f8c912aa31e3f67d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 1 Jun 2020 13:19:35 +0200 Subject: [PATCH] :tada: Add html emails. --- backend/deps.edn | 3 +- backend/resources/emails/base.html | 85 +++++++++ backend/resources/emails/change-email/en.html | 19 ++ backend/resources/emails/change-email/en.subj | 1 + .../change-email/{en.mustache => en.txt} | 10 +- .../resources/emails/debug-email-list.html | 14 -- .../emails/partials/en/footer.mustache | 46 ----- .../resources/emails/partials/head.mustache | 6 - .../emails/partials/inline_style.html | 173 ++++++++++++++++++ .../emails/partials/inline_style.mustache | 162 ---------------- .../emails/password-recovery/en.html | 22 +++ .../emails/password-recovery/en.subj | 1 + .../password-recovery/{en.mustache => en.txt} | 8 +- backend/resources/emails/register/en.html | 20 ++ backend/resources/emails/register/en.subj | 1 + .../emails/register/{en.mustache => en.txt} | 8 +- backend/resources/emails/register/fr.mustache | 17 -- .../public/static/images/email/instagram.png | Bin 0 -> 901 bytes .../public/static/images/email/taiga.png | Bin 0 -> 604 bytes .../public/static/images/email/uxbox.png | Bin 0 -> 746 bytes backend/src/uxbox/config.clj | 4 +- backend/src/uxbox/emails.clj | 3 +- backend/src/uxbox/migrations.clj | 3 +- .../src/uxbox/services/mutations/profile.clj | 3 - backend/src/uxbox/tasks.clj | 6 +- backend/src/uxbox/util/emails.clj | 60 ++---- backend/src/uxbox/util/template.clj | 59 ++---- 27 files changed, 368 insertions(+), 366 deletions(-) create mode 100644 backend/resources/emails/base.html create mode 100644 backend/resources/emails/change-email/en.html create mode 100644 backend/resources/emails/change-email/en.subj rename backend/resources/emails/change-email/{en.mustache => en.txt} (66%) delete mode 100644 backend/resources/emails/debug-email-list.html delete mode 100644 backend/resources/emails/partials/en/footer.mustache delete mode 100644 backend/resources/emails/partials/head.mustache create mode 100644 backend/resources/emails/partials/inline_style.html delete mode 100644 backend/resources/emails/partials/inline_style.mustache create mode 100644 backend/resources/emails/password-recovery/en.html create mode 100644 backend/resources/emails/password-recovery/en.subj rename backend/resources/emails/password-recovery/{en.mustache => en.txt} (66%) create mode 100644 backend/resources/emails/register/en.html create mode 100644 backend/resources/emails/register/en.subj rename backend/resources/emails/register/{en.mustache => en.txt} (61%) delete mode 100644 backend/resources/emails/register/fr.mustache create mode 100644 backend/resources/public/static/images/email/instagram.png create mode 100644 backend/resources/public/static/images/email/taiga.png create mode 100644 backend/resources/public/static/images/email/uxbox.png diff --git a/backend/deps.edn b/backend/deps.edn index 9a43a21467..bf334bc380 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -19,8 +19,9 @@ io.prometheus/simpleclient_hotspot {:mvn/version "0.9.0"} io.prometheus/simpleclient_httpserver {:mvn/version "0.9.0"} + selmer/selmer {:mvn/version "1.12.18"} + expound/expound {:mvn/version "0.8.4"} - instaparse/instaparse {:mvn/version "1.4.10"} com.cognitect/transit-clj {:mvn/version "1.0.324"} io.lettuce/lettuce-core {:mvn/version "5.2.2.RELEASE"} diff --git a/backend/resources/emails/base.html b/backend/resources/emails/base.html new file mode 100644 index 0000000000..d399ce6c4b --- /dev/null +++ b/backend/resources/emails/base.html @@ -0,0 +1,85 @@ + + + + + + {% block head %} + UXBOX Email + {% endblock %} + {% include "emails/partials/inline_style.html" %} + + + + + + + + + + + +
+ + + +
+ + + + +
+ {% block content %} + {% endblock %} +
+
+ + +
+ + + + + + + + + + + + + + diff --git a/backend/resources/emails/change-email/en.html b/backend/resources/emails/change-email/en.html new file mode 100644 index 0000000000..da7652f584 --- /dev/null +++ b/backend/resources/emails/change-email/en.html @@ -0,0 +1,19 @@ +{% extends "emails/base.html" %} + +{% block content %} +

Hello {{name}}!

+ +

We received a request to change your current email to {{ pending-email }}.

+ +

Click to the link below to confirm the change:

+ + Confirm email change + +

If you received this email by mistake, please consider changing your password + for security reasons.

+ +

Enjoy!

+ +

The UXBOX team.

+ +{% endblock %} diff --git a/backend/resources/emails/change-email/en.subj b/backend/resources/emails/change-email/en.subj new file mode 100644 index 0000000000..fae232cbdb --- /dev/null +++ b/backend/resources/emails/change-email/en.subj @@ -0,0 +1 @@ +Email change \ No newline at end of file diff --git a/backend/resources/emails/change-email/en.mustache b/backend/resources/emails/change-email/en.txt similarity index 66% rename from backend/resources/emails/change-email/en.mustache rename to backend/resources/emails/change-email/en.txt index 93ed9a5772..f4232aac44 100644 --- a/backend/resources/emails/change-email/en.mustache +++ b/backend/resources/emails/change-email/en.txt @@ -1,19 +1,13 @@ --- begin :subject -Email change. --- end - --- begin :body-text Hello {{name}}! -We received a request to change your current email to {{ pendingEmail }}. +We received a request to change your current email to {{ pending-email }}. Click to the link below to confirm the change: -{{ publicUri }}/#/auth/verify-token?token={{token}} +{{ public-uri }}/#/auth/verify-token?token={{token}} If you received this email by mistake, please consider changing your password for security reasons. Enjoy! The UXBOX team. --- end diff --git a/backend/resources/emails/debug-email-list.html b/backend/resources/emails/debug-email-list.html deleted file mode 100644 index b2827e29e2..0000000000 --- a/backend/resources/emails/debug-email-list.html +++ /dev/null @@ -1,14 +0,0 @@ - - -
-

Available Emails:

- -
- - diff --git a/backend/resources/emails/partials/en/footer.mustache b/backend/resources/emails/partials/en/footer.mustache deleted file mode 100644 index 09b9ceec91..0000000000 --- a/backend/resources/emails/partials/en/footer.mustache +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - diff --git a/backend/resources/emails/partials/head.mustache b/backend/resources/emails/partials/head.mustache deleted file mode 100644 index 9c6f296a97..0000000000 --- a/backend/resources/emails/partials/head.mustache +++ /dev/null @@ -1,6 +0,0 @@ - - - - title - {{> inline_style }} - diff --git a/backend/resources/emails/partials/inline_style.html b/backend/resources/emails/partials/inline_style.html new file mode 100644 index 0000000000..c40ccfd43a --- /dev/null +++ b/backend/resources/emails/partials/inline_style.html @@ -0,0 +1,173 @@ + diff --git a/backend/resources/emails/partials/inline_style.mustache b/backend/resources/emails/partials/inline_style.mustache deleted file mode 100644 index b2a28a0f86..0000000000 --- a/backend/resources/emails/partials/inline_style.mustache +++ /dev/null @@ -1,162 +0,0 @@ - diff --git a/backend/resources/emails/password-recovery/en.html b/backend/resources/emails/password-recovery/en.html new file mode 100644 index 0000000000..c0e0767edf --- /dev/null +++ b/backend/resources/emails/password-recovery/en.html @@ -0,0 +1,22 @@ +{% extends "emails/base.html" %} + +{% block content %} +

Hello {{name}}!

+ +

We received a request to reset your password. Click the link + below to choose a new one:

+ + + Reset password. + + +

+ If you received this email by mistake, you can safely ignore + it. Your password won't be changed. +

+ +

Enjoy!

+ +

The UXBOX team.

+ +{% endblock %} diff --git a/backend/resources/emails/password-recovery/en.subj b/backend/resources/emails/password-recovery/en.subj new file mode 100644 index 0000000000..bca0a5e0b3 --- /dev/null +++ b/backend/resources/emails/password-recovery/en.subj @@ -0,0 +1 @@ +Password reset \ No newline at end of file diff --git a/backend/resources/emails/password-recovery/en.mustache b/backend/resources/emails/password-recovery/en.txt similarity index 66% rename from backend/resources/emails/password-recovery/en.mustache rename to backend/resources/emails/password-recovery/en.txt index f419e46a60..cbd00e35b8 100644 --- a/backend/resources/emails/password-recovery/en.mustache +++ b/backend/resources/emails/password-recovery/en.txt @@ -1,18 +1,12 @@ --- begin :subject -Password reset. --- end - --- begin :body-text Hello {{name}}! We received a request to reset your password. Click the link below to choose a new one: -{{ publicUri }}/#/auth/recovery?token={{token}} +{{ public-uri }}/#/auth/recovery?token={{token}} If you received this email by mistake, you can safely ignore it. Your password won't be changed. Enjoy! The UXBOX team. --- end diff --git a/backend/resources/emails/register/en.html b/backend/resources/emails/register/en.html new file mode 100644 index 0000000000..a7dd1d9acb --- /dev/null +++ b/backend/resources/emails/register/en.html @@ -0,0 +1,20 @@ +{% extends "emails/base.html" %} + +{% block content %} +

Hello {{name}}!

+ +

+ Thanks for signing up for your UXBOX account! Please verify your + email using the link below adn get started building mockups and + prototypes today! +

+ + + Verify token + + +

Enjoy!

+ +

The UXBOX team.

+ +{% endblock %} diff --git a/backend/resources/emails/register/en.subj b/backend/resources/emails/register/en.subj new file mode 100644 index 0000000000..4b49d94ba3 --- /dev/null +++ b/backend/resources/emails/register/en.subj @@ -0,0 +1 @@ +Verify email. diff --git a/backend/resources/emails/register/en.mustache b/backend/resources/emails/register/en.txt similarity index 61% rename from backend/resources/emails/register/en.mustache rename to backend/resources/emails/register/en.txt index ff63fd0b78..70efbfe173 100644 --- a/backend/resources/emails/register/en.mustache +++ b/backend/resources/emails/register/en.txt @@ -1,15 +1,9 @@ --- begin :subject -Verify email. --- end - --- begin :body-text Hello {{name}}! Thanks for signing up for your UXBOX account! Please verify your email using the link below adn get started building mockups and prototypes today! -{{ publicUri }}/#/auth/verify-token?token={{token}} +{{ public-uri }}/#/auth/verify-token?token={{token}} Enjoy! The UXBOX team. --- end \ No newline at end of file diff --git a/backend/resources/emails/register/fr.mustache b/backend/resources/emails/register/fr.mustache deleted file mode 100644 index b4a5301490..0000000000 --- a/backend/resources/emails/register/fr.mustache +++ /dev/null @@ -1,17 +0,0 @@ --- begin :subject -Bienvenue sur UXBOX. --- end - --- begin :body-text -Bonjour {{user}}! - -Bienvenue sur UXBOX. - -L'équipe UXBOX. --- end - --- begin :body-html -

Bonjour {{user}} !

-

Bienvenue sur UXBOX.

-

L'équipe UXBOX.

--- end \ No newline at end of file diff --git a/backend/resources/public/static/images/email/instagram.png b/backend/resources/public/static/images/email/instagram.png new file mode 100644 index 0000000000000000000000000000000000000000..107e25ebc1d225bfc125307545d32dad65ba4ba8 GIT binary patch literal 901 zcmV;01A6?4P)P000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP87jJjC4@BQFtD6~`w6ADgeVzq z2nqP2sw=dvCCibpmm;I zu@Ri z-(=5ZtUvO1XELT8gQZ{)VkhAV*|n=4lNWsT=!{Qu#L<8Q#PXFRhn2|m+?IeJL}4r> z@dLsqU{^Y>+nxn!*rkd@QJr0A+4kP=Znxcx!cmJzzz;E0tV0zrIfWU5Z3BloBKJ;TW8_eK7U!LiT!IbFdVN2q#l;+2q)ErT%c8Bg(n2 z*i?_hnG503X!M?ktMI+sX*W4fa$JoItWK?1suWmbPa$SFuX7xBc>_=Aah{ySkvy;@ z`RL+$-9zgxO#Nu9Ya%BkkhPwBxC0AB1&8}GYE;>%P2JAnzEo%M6VH=}OH^IH$y(GI z(tckNY~wCIbjfd76c+$QnjM63Y`#3w9%-ACSnl=GSfVxj^y$fx4hb(5!3YC_c}@+< zcemvkmvNJkZdNMo6<|e?mJoDATl>w500000NkvXXu0mjfx4oDZ literal 0 HcmV?d00001 diff --git a/backend/resources/public/static/images/email/taiga.png b/backend/resources/public/static/images/email/taiga.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ae46f5dc3702b37edf3828bc04848f6af65a1e GIT binary patch literal 604 zcmV-i0;BzjP)X1^@s6D=Y3@00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPjZ>KEu%1_DBQImP+v>=t0fN8veVYb@ z>&rZHl!qyde%D}3-ys@PPm<%yuVftq&1P$#i5dWFMWorVHpKS|^q&ELK~Nj;AH}pu zihRTD3s0aJ-CpnTV8-Y8z>vBpm_UYs2u!t*Jp94VtU+13VBulr%x?KE%crsvPo;M# zjr1`)Tk?T8lTiZ6$)TfDEi#C9ja9)|x&g<4O(KO-SW3jXzA)U2(}}uWjFv(mRILuH zYfg&excc-m>JVWcYXx=Fk@v6i{5rl6X1^@s6D=Y3@00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPj?(_IDmqG2l47FiL38z+<2dH3 z10dzZwk!Ef9Jp!W!l|_p=?wvzC}n9l{4}-8HJ3M>2fqIHh~s*A^zWEq3WR3h9~3;V zJ(;UjR~Ij8Di77KaCVP~O@uWKa9AOeq_V-D^0AI;}Kzv6?E09Pci z&aW;J<~I??MaB*Vk+|cudSRd+^I1(3L9N^PbmZay^im$*~y} z$&n(Cn0Pqsw${~w1}RWNY&@r0eaA#@$euo}NR>}F3ia!Cq?rYl81#DI*cAANskTv! ze7&%ZcnJYJfKztQ1vk%1zO%qS_%HAe3dAj9Ps9_BATeT-y@;U2{io@aYjqwtZol8V zg$z(F1BuRqh>C36L3sFMt-!K!-#ax65nU%9k(-5{dJ#3bWteKZab+JruaVStXzmzT&@)pOP*>>9Hz94O#N8(A{h#fiY)a`0JGTRK)>Cks<* (io/resource path) + (tmpl/render context)))) + (defn- impl-build-email [id context] (let [lang (:lang context :en) - path (str/format email-path {:id (name id) :lang (name lang)})] - (-> (tmpl/render path context) - (parse-template) - (build-base-email context)))) + subj (render-email-part :subj id context) + html (render-email-part :html id context) + text (render-email-part :txt id context)] + + {:subject subj + :content (cond-> [] + text (conj {:type "text/plain" + :value text}) + html (conj {:type "text/html" + :value html}))})) ;; --- Public API diff --git a/backend/src/uxbox/util/template.clj b/backend/src/uxbox/util/template.clj index 4260682bd4..becb12911f 100644 --- a/backend/src/uxbox/util/template.clj +++ b/backend/src/uxbox/util/template.clj @@ -12,57 +12,24 @@ [clojure.walk :as walk] [clojure.java.io :as io] [cuerdas.core :as str] - [uxbox.common.exceptions :as ex]) - (:import - java.io.StringReader - java.util.HashMap - java.util.function.Function; - com.github.mustachejava.DefaultMustacheFactory - com.github.mustachejava.Mustache)) - -(def ^DefaultMustacheFactory +mustache-factory+ (DefaultMustacheFactory.)) - -(defn- adapt-context - [data] - (walk/postwalk (fn [x] - (cond - (instance? clojure.lang.Named x) - (str/camel (name x)) - - (instance? clojure.lang.MapEntry x) - x - - (fn? x) - (reify Function - (apply [this content] - (try - (x content) - (catch Exception e - (log/error e "Error on executing" x) - "")))) - - (or (vector? x) (list? x)) - (java.util.ArrayList. ^java.util.List x) - - (map? x) - (java.util.HashMap. ^java.util.Map x) - - (set? x) - (java.util.HashSet. ^java.util.Set x) - - :else - x)) - data)) + [selmer.parser :as sp] + [uxbox.common.exceptions :as ex])) +;; (sp/cache-off!) (defn render [path context] (try - (let [context (adapt-context context) - template (.compile +mustache-factory+ path)] - (with-out-str - (let [scope (HashMap. ^java.util.Map (walk/stringify-keys context))] - (.execute ^Mustache template *out* scope)))) + (sp/render-file path context) + (catch Exception cause + (ex/raise :type :internal + :code :template-render-error + :cause cause)))) + +(defn render-string + [content context] + (try + (sp/render content context) (catch Exception cause (ex/raise :type :internal :code :template-render-error