Skip to content

Commit

Permalink
✨(emails) use mjml to generate html and text emails
Browse files Browse the repository at this point in the history
Introducing MJML, a responsive email framework, to reduce the pain of writing
responsive emails.
  • Loading branch information
wilbrdt committed Aug 9, 2024
1 parent 4e70cbc commit 9bd449f
Show file tree
Hide file tree
Showing 12 changed files with 1,415 additions and 4 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ ENV/
env.bak/
venv.bak/

# npm
node_modules

# Mails
src/mork/mail/templates/

# Logs
*.log

Expand Down
30 changes: 26 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
SHELL := /bin/bash

# -- Docker
COMPOSE = bin/compose
COMPOSE_EXEC = $(COMPOSE) exec
COMPOSE_RUN = $(COMPOSE) run --rm --no-deps
COMPOSE_RUN_API = $(COMPOSE_RUN) api
COMPOSE = bin/compose
COMPOSE_EXEC = $(COMPOSE) exec
COMPOSE_RUN = $(COMPOSE) run --rm --no-deps
COMPOSE_RUN_API = $(COMPOSE_RUN) api
COMPOSE_RUN_MAIL = $(COMPOSE_RUN) mail-generator

# -- Postgresql
DB_HOST = postgresql
Expand All @@ -21,6 +22,8 @@ MORK_TEST_DB_NAME ?= test-mork-db
# -- Celery
MORK_CELERY_SERVER_PORT ?= 5555

# -- Mail
MAIL_YARN = $(COMPOSE_RUN_MAIL) yarn

# ==============================================================================
# RULES
Expand Down Expand Up @@ -159,6 +162,25 @@ test: \
.PHONY: test


# -- Mail generator

mails-build: ## Convert mjml files to html and text
@$(MAIL_YARN) build
.PHONY: mails-build

mails-build-html-to-plain-text: ## Convert html files to text
@$(MAIL_YARN) build-html-to-plain-text
.PHONY: mails-build-html-to-plain-text

mails-build-mjml-to-html: ## Convert mjml files to html and text
@$(MAIL_YARN) build-mjml-to-html
.PHONY: mails-build-mjml-to-html

mails-install: ## mail-generator yarn install
@$(MAIL_YARN) install
.PHONY: mails-install


# -- Misc
help:
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
Expand Down
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,12 @@ services:
image: sj26/mailcatcher:latest
ports:
- "1081:1080"

mail-generator:
image: node:18.18
user: "${DOCKER_USER:-1000}"
environment:
HOME: /tmp
volumes:
- ".:/app"
working_dir: /app/src/mork/mail
22 changes: 22 additions & 0 deletions src/mork/mail/bin/html-to-plain-text
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -eo pipefail
# Run html-to-text to convert all html files to text files
DIR_MAILS="./templates/"

if [ ! -d "${DIR_MAILS}" ]; then
mkdir -p "${DIR_MAILS}";
fi

if [ ! -d "${DIR_MAILS}"html/ ]; then
mkdir -p "${DIR_MAILS}"html/;
exit;
fi

for file in "${DIR_MAILS}"html/*.html;
do html-to-text -j ./html-to-text.config.json < "$file" > "${file%.html}".txt; done;

if [ ! -d "${DIR_MAILS}"text/ ]; then
mkdir -p "${DIR_MAILS}"text/;
fi

mv "${DIR_MAILS}"html/*.txt "${DIR_MAILS}"text/;
9 changes: 9 additions & 0 deletions src/mork/mail/bin/mjml-to-html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

# Run mjml command to convert all mjml templates to html files
DIR_MAILS="./templates/html"

if [ ! -d "${DIR_MAILS}" ]; then
mkdir -p "${DIR_MAILS}";
fi
mjml mjml/*.mjml -o "${DIR_MAILS}";
11 changes: 11 additions & 0 deletions src/mork/mail/html-to-text.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"wordwrap": 600,
"selectors": [
{
"selector": "h1",
"options": {
"uppercase": false
}
}
]
}
Binary file added src/mork/mail/images/logo_fun.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/mork/mail/mjml/partial/footer.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<mj-section padding="0">
<mj-column>
<mj-text mj-class="text--small" align="center" padding="20px 20px">
Cet email a été envoyé à {{ email }} par <a href="{{ href }}">{{ name }}</a>
</mj-text>
</mj-column>
</mj-section>
47 changes: 47 additions & 0 deletions src/mork/mail/mjml/partial/header.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<mj-head>
<mj-title>{{ title }}</mj-title>
<mj-preview>
{{ title }}
</mj-preview>
<mj-attributes>
<mj-font name="Roboto" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700;900&display=swap" />
<mj-all
font-family="Roboto, -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
font-size="16px"
line-height="1.5em"
color="#031963"
/>
<mj-class name="text--small" font-size="0.875rem" />
<mj-class name="bg--blue-100" background-color="#EDF5FA" />
</mj-attributes>
<mj-style>
/* Reset */
h1, h2, h3, h4, h5, h6, p {
margin: 0;
padding: 0;
}

a {
color: inherit;
}
</mj-style>
<mj-style>
/* Global styles */
h1 {
color: #055FD2;
font-size: 2rem;
line-height: 1em;
font-weight: 700;
}

<!-- .blue-button {
background-color: #055FD2;
} -->

.wrapper {
background: #FFFFFF;
border-radius: 0 0 6px 6px;
box-shadow: 0 0 6px rgba(2 117 180 / 0.3);
}
</mj-style>
</mj-head>
44 changes: 44 additions & 0 deletions src/mork/mail/mjml/warning_email.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<mjml>
<mj-include path="./partial/header.mjml" />
<mj-body mj-class="bg--blue-100">
<mj-wrapper css-class="wrapper" padding="20px 40px 40px 40px">
<mj-section>
<mj-column>
<mj-image src="../images/logo_fun.png" width="200px" align="left" alt="Logo de FUN" />
</mj-column>
</mj-section>
<mj-section mj-class="bg--blue-100" padding="20px 40px 0 40px">
<mj-column>
<mj-text align="center" padding="0 0 20px 0">
<h1>Votre compte va être supprimé dans 30 jours.</h1>
</mj-text>
</mj-column>
</mj-section>
<mj-section mj-class="bg--blue-100" border-radius="6px 6px 0 0" padding="20px 40px 20px 40px">
<mj-column>
<mj-text padding="0">
<p>
{{ fullname }},<br/>
Vous ne vous êtes pas connectés sur fun-mooc.fr depuis longtemps.
<br/>
Malheureusement, sans action de votre part et
conformément à notre politique de protection des données, nous procéderons
à la suppression de votre compte dans 30 jours.
<br/>
<br/>
Si vous souhaitez conservez votre compte, veuillez vous connecter à la plateforme.
</p>
</mj-text>
</mj-column>
</mj-section>
<mj-section mj-class="bg--blue-100" border-radius="0 0 6px 6px" padding="0 50px 30px 50px">
<mj-column>
<mj-button background-color="#055FD2" color="white" href="https://lms.fun-mooc.fr/login">
Se connecter
</mj-button>
</mj-column>
</mj-section>
</mj-wrapper>
<mj-include path="./partial/footer.mjml" />
</mj-body>
</mjml>
23 changes: 23 additions & 0 deletions src/mork/mail/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "mail_mjml",
"version": "2.5.1",
"description": "An util to generate html and text jinja templates from mjml templates",
"type": "module",
"dependencies": {
"@html-to/text-cli": "0.5.4",
"mjml": "4.15.3"
},
"private": true,
"scripts": {
"build-mjml-to-html": "./bin/mjml-to-html",
"build-html-to-plain-text": "./bin/html-to-plain-text",
"build": "yarn build-mjml-to-html; yarn build-html-to-plain-text;"
},
"volta": {
"node": "16.15.1"
},
"repository": "https://github.com/openfun/mork",
"author": "France Université Numérique",
"license": "MIT"
}

Loading

0 comments on commit 9bd449f

Please sign in to comment.