Upgrade djlint and reformat all fiels (#2197)

* update djlint

* reformat all files

* update precommit version

---------

Co-authored-by: Son NK <son@simplelogin.io>
This commit is contained in:
Son Nguyen Kim 2024-08-28 13:07:34 +02:00 committed by GitHub
parent c1625a8002
commit d49f6b88a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
110 changed files with 1947 additions and 2297 deletions

View file

@ -8,7 +8,7 @@ repos:
- id: check-yaml - id: check-yaml
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/Riverside-Healthcare/djLint - repo: https://github.com/Riverside-Healthcare/djLint
rev: v1.3.0 rev: v1.34.1
hooks: hooks:
- id: djlint-jinja - id: djlint-jinja
files: '.*\.html' files: '.*\.html'
@ -21,5 +21,4 @@ repos:
- id: ruff - id: ruff
args: [ --fix ] args: [ --fix ]
# Run the formatter. # Run the formatter.
- id: ruff-format - id: ruff-format

View file

@ -223,6 +223,7 @@ Now open http://localhost:1080/ (or http://localhost:1080/ for MailHog), you sho
## Job runner ## Job runner
Some features require a job handler (such as GDPR data export). To test such feature you need to run the job_runner Some features require a job handler (such as GDPR data export). To test such feature you need to run the job_runner
```bash ```bash
python job_runner.py python job_runner.py
``` ```
@ -248,4 +249,5 @@ poetry install
# activate the virtualenv and you should be good to go! # activate the virtualenv and you should be good to go!
source .venv/bin/activate source .venv/bin/activate
``` ```

392
poetry.lock generated
View file

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]] [[package]]
name = "aiohttp" name = "aiohttp"
@ -276,21 +276,6 @@ files = [
{file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
] ]
[[package]]
name = "backports.entry-points-selectable"
version = "1.1.1"
description = "Compatibility shim providing selectable entry points for older implementations"
optional = false
python-versions = ">=2.7"
files = [
{file = "backports.entry_points_selectable-1.1.1-py2.py3-none-any.whl", hash = "sha256:7fceed9532a7aa2bd888654a7314f864a3c16a4e710b34a58cfc0f08114c663b"},
{file = "backports.entry_points_selectable-1.1.1.tar.gz", hash = "sha256:914b21a479fde881635f7af5adc7f6e38d6b274be32269070c53b698c60d5386"},
]
[package.extras]
docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"]
testing = ["pytest", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"]
[[package]] [[package]]
name = "bcrypt" name = "bcrypt"
version = "3.2.0" version = "3.2.0"
@ -491,13 +476,13 @@ pycparser = "*"
[[package]] [[package]]
name = "cfgv" name = "cfgv"
version = "3.2.0" version = "3.4.0"
description = "Validate configuration and produce human readable error messages." description = "Validate configuration and produce human readable error messages."
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.8"
files = [ files = [
{file = "cfgv-3.2.0-py2.py3-none-any.whl", hash = "sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d"}, {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
{file = "cfgv-3.2.0.tar.gz", hash = "sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
] ]
[[package]] [[package]]
@ -690,6 +675,21 @@ sdist = ["setuptools-rust (>=0.11.4)"]
ssh = ["bcrypt (>=3.1.5)"] ssh = ["bcrypt (>=3.1.5)"]
test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"] test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"]
[[package]]
name = "cssbeautifier"
version = "1.15.1"
description = "CSS unobfuscator and beautifier."
optional = false
python-versions = "*"
files = [
{file = "cssbeautifier-1.15.1.tar.gz", hash = "sha256:9f7064362aedd559c55eeecf6b6bed65e05f33488dcbe39044f0403c26e1c006"},
]
[package.dependencies]
editorconfig = ">=0.12.2"
jsbeautifier = "*"
six = ">=1.13.0"
[[package]] [[package]]
name = "decorator" name = "decorator"
version = "4.4.2" version = "4.4.2"
@ -734,41 +734,40 @@ graph = ["objgraph (>=1.7.2)"]
[[package]] [[package]]
name = "distlib" name = "distlib"
version = "0.3.1" version = "0.3.8"
description = "Distribution utilities" description = "Distribution utilities"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
{file = "distlib-0.3.1-py2.py3-none-any.whl", hash = "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb"}, {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
{file = "distlib-0.3.1.zip", hash = "sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1"}, {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
] ]
[[package]] [[package]]
name = "djlint" name = "djlint"
version = "1.3.0" version = "1.34.1"
description = "HTML Template Linter and Formatter" description = "HTML Template Linter and Formatter"
optional = false optional = false
python-versions = ">=3.7,<4.0" python-versions = ">=3.8.0,<4.0.0"
files = [ files = [
{file = "djlint-1.3.0-py3-none-any.whl", hash = "sha256:0c986bf542cdac3025d431a5b15e6c3977f652f2e76e408dbb5e7aaab6b73d99"}, {file = "djlint-1.34.1-py3-none-any.whl", hash = "sha256:96ff1c464fb6f061130ebc88663a2ea524d7ec51f4b56221a2b3f0320a3cfce8"},
{file = "djlint-1.3.0.tar.gz", hash = "sha256:b2d8e6c0a14f88da165296f0da05795d15299b7ab0a9093d670ce9ffd867bc79"}, {file = "djlint-1.34.1.tar.gz", hash = "sha256:db93fa008d19eaadb0454edf1704931d14469d48508daba2df9941111f408346"},
] ]
[package.dependencies] [package.dependencies]
click = ">=8.0.1,<9.0.0" click = ">=8.0.1,<9.0.0"
colorama = ">=0.4.4,<0.5.0" colorama = ">=0.4.4,<0.5.0"
cssbeautifier = ">=1.14.4,<2.0.0"
html-tag-names = ">=0.1.2,<0.2.0" html-tag-names = ">=0.1.2,<0.2.0"
html-void-elements = ">=0.1.0,<0.2.0" html-void-elements = ">=0.1.0,<0.2.0"
importlib-metadata = ">=4.11.0,<5.0.0" jsbeautifier = ">=1.14.4,<2.0.0"
pathspec = ">=0.9.0,<0.10.0" json5 = ">=0.9.11,<0.10.0"
pathspec = ">=0.12.0,<0.13.0"
PyYAML = ">=6.0,<7.0" PyYAML = ">=6.0,<7.0"
regex = ">=2022.1.18,<2023.0.0" regex = ">=2023.0.0,<2024.0.0"
tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""}
tqdm = ">=4.62.2,<5.0.0" tqdm = ">=4.62.2,<5.0.0"
[package.extras]
test = ["coverage (>=6.3.1,<7.0.0)", "pytest (>=7.0.1,<8.0.0)", "pytest-cov (>=3.0.0,<4.0.0)"]
[[package]] [[package]]
name = "dkimpy" name = "dkimpy"
version = "1.0.5" version = "1.0.5"
@ -806,6 +805,16 @@ doh = ["requests", "requests-toolbelt"]
idna = ["idna (>=2.1)"] idna = ["idna (>=2.1)"]
trio = ["sniffio (>=1.1)", "trio (>=0.14.0)"] trio = ["sniffio (>=1.1)", "trio (>=0.14.0)"]
[[package]]
name = "editorconfig"
version = "0.12.4"
description = "EditorConfig File Locator and Interpreter for Python"
optional = false
python-versions = "*"
files = [
{file = "EditorConfig-0.12.4.tar.gz", hash = "sha256:24857fa1793917dd9ccf0c7810a07e05404ce9b823521c7dce22a4fb5d125f80"},
]
[[package]] [[package]]
name = "email-validator" name = "email-validator"
version = "1.1.3" version = "1.1.3"
@ -851,15 +860,20 @@ requests = "*"
[[package]] [[package]]
name = "filelock" name = "filelock"
version = "3.0.12" version = "3.15.4"
description = "A platform independent file lock." description = "A platform independent file lock."
optional = false optional = false
python-versions = "*" python-versions = ">=3.8"
files = [ files = [
{file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"},
{file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"},
] ]
[package.extras]
docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"]
typing = ["typing-extensions (>=4.8)"]
[[package]] [[package]]
name = "flanker" name = "flanker"
version = "0.9.11" version = "0.9.11"
@ -1358,7 +1372,6 @@ files = [
{file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"},
{file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"},
{file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"},
{file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d967650d3f56af314b72df7089d96cda1083a7fc2da05b375d2bc48c82ab3f3c"},
{file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"},
{file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"},
{file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"},
@ -1367,7 +1380,6 @@ files = [
{file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"},
{file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"},
{file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"},
{file = "greenlet-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d4606a527e30548153be1a9f155f4e283d109ffba663a15856089fb55f933e47"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"},
@ -1397,7 +1409,6 @@ files = [
{file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"},
{file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"},
{file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"},
{file = "greenlet-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1087300cf9700bbf455b1b97e24db18f2f77b55302a68272c56209d5587c12d1"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"},
@ -1406,7 +1417,6 @@ files = [
{file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"},
{file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"},
{file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"},
{file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8512a0c38cfd4e66a858ddd1b17705587900dd760c6003998e9472b77b56d417"},
{file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"},
{file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"},
{file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"},
@ -1495,17 +1505,17 @@ pyreadline = {version = "*", markers = "sys_platform == \"win32\""}
[[package]] [[package]]
name = "identify" name = "identify"
version = "1.5.5" version = "2.6.0"
description = "File identification library for Python" description = "File identification library for Python"
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" python-versions = ">=3.8"
files = [ files = [
{file = "identify-1.5.5-py2.py3-none-any.whl", hash = "sha256:da683bfb7669fa749fc7731f378229e2dbf29a1d1337cbde04106f02236eb29d"}, {file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"},
{file = "identify-1.5.5.tar.gz", hash = "sha256:7c22c384a2c9b32c5cc891d13f923f6b2653aa83e2d75d8f79be240d6c86c4f4"}, {file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"},
] ]
[package.extras] [package.extras]
license = ["editdistance"] license = ["ukkonen"]
[[package]] [[package]]
name = "idna" name = "idna"
@ -1518,25 +1528,6 @@ files = [
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
] ]
[[package]]
name = "importlib-metadata"
version = "4.12.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.7"
files = [
{file = "importlib_metadata-4.12.0-py3-none-any.whl", hash = "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"},
{file = "importlib_metadata-4.12.0.tar.gz", hash = "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670"},
]
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
perf = ["ipython"]
testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
[[package]] [[package]]
name = "iniconfig" name = "iniconfig"
version = "1.0.1" version = "1.0.1"
@ -1669,6 +1660,31 @@ files = [
{file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"}, {file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"},
] ]
[[package]]
name = "jsbeautifier"
version = "1.15.1"
description = "JavaScript unobfuscator and beautifier."
optional = false
python-versions = "*"
files = [
{file = "jsbeautifier-1.15.1.tar.gz", hash = "sha256:ebd733b560704c602d744eafc839db60a1ee9326e30a2a80c4adb8718adc1b24"},
]
[package.dependencies]
editorconfig = ">=0.12.2"
six = ">=1.13.0"
[[package]]
name = "json5"
version = "0.9.25"
description = "A Python implementation of the JSON5 data format."
optional = false
python-versions = ">=3.8"
files = [
{file = "json5-0.9.25-py3-none-any.whl", hash = "sha256:34ed7d834b1341a86987ed52f3f76cd8ee184394906b6e22a1e0deb9ab294e8f"},
{file = "json5-0.9.25.tar.gz", hash = "sha256:548e41b9be043f9426776f05df8635a00fe06104ea51ed24b67f908856e151ae"},
]
[[package]] [[package]]
name = "jwcrypto" name = "jwcrypto"
version = "0.8" version = "0.8"
@ -1959,13 +1975,13 @@ urllib3 = ">=1.7,<2"
[[package]] [[package]]
name = "nodeenv" name = "nodeenv"
version = "1.5.0" version = "1.9.1"
description = "Node.js virtual environment builder" description = "Node.js virtual environment builder"
optional = false optional = false
python-versions = "*" python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [ files = [
{file = "nodeenv-1.5.0-py2.py3-none-any.whl", hash = "sha256:5304d424c529c997bc888453aeaa6362d242b6b4631e90f3d4bf1b290f1c84a9"}, {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
{file = "nodeenv-1.5.0.tar.gz", hash = "sha256:ab45090ae383b716c4ef89e690c41ff8c2b257b85b309f01f3654df3d084bd7c"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
] ]
[[package]] [[package]]
@ -2015,13 +2031,13 @@ testing = ["docopt", "pytest (>=3.0.7)"]
[[package]] [[package]]
name = "pathspec" name = "pathspec"
version = "0.9.0" version = "0.12.1"
description = "Utility library for gitignore style pattern matching of file paths." description = "Utility library for gitignore style pattern matching of file paths."
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" python-versions = ">=3.8"
files = [ files = [
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
] ]
[[package]] [[package]]
@ -2117,13 +2133,13 @@ files = [
[[package]] [[package]]
name = "pre-commit" name = "pre-commit"
version = "2.17.0" version = "3.8.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks." description = "A framework for managing and maintaining multi-language pre-commit hooks."
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.9"
files = [ files = [
{file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"}, {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"},
{file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"}, {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"},
] ]
[package.dependencies] [package.dependencies]
@ -2131,8 +2147,7 @@ cfgv = ">=2.0.0"
identify = ">=1.0.0" identify = ">=1.0.0"
nodeenv = ">=0.11.1" nodeenv = ">=0.11.1"
pyyaml = ">=5.1" pyyaml = ">=5.1"
toml = "*" virtualenv = ">=20.10.0"
virtualenv = ">=20.0.8"
[[package]] [[package]]
name = "prompt-toolkit" name = "prompt-toolkit"
@ -2665,85 +2680,104 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
[[package]] [[package]]
name = "regex" name = "regex"
version = "2022.6.2" version = "2023.12.25"
description = "Alternative regular expression module, to replace re." description = "Alternative regular expression module, to replace re."
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.7"
files = [ files = [
{file = "regex-2022.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:042d122f9fee3ceb6d7e3067d56557df697d1aad4ff5f64ecce4dc13a90a7c01"}, {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"},
{file = "regex-2022.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffef4b30785dc2d1604dfb7cf9fca5dc27cd86d65f7c2a9ec34d6d3ae4565ec2"}, {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"},
{file = "regex-2022.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0afa6a601acf3c0dc6de4e8d7d8bbce4e82f8542df746226cd35d4a6c15e9456"}, {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"},
{file = "regex-2022.6.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a11cbe8eb5fb332ae474895b5ead99392a4ea568bd2a258ab8df883e9c2bf92"}, {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"},
{file = "regex-2022.6.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c1f62ee2ba880e221bc950651a1a4b0176083d70a066c83a50ef0cb9b178e12"}, {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"},
{file = "regex-2022.6.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aba3d13c77173e9bfed2c2cea7fc319f11c89a36fcec08755e8fb169cf3b0df"}, {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"},
{file = "regex-2022.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249437f7f5b233792234aeeecb14b0aab1566280de42dfc97c26e6f718297d68"}, {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"},
{file = "regex-2022.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:179410c79fa86ef318d58ace233f95b87b05a1db6dc493fa29404a43f4b215e2"}, {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"},
{file = "regex-2022.6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5e201b1232d81ca1a7a22ab2f08e1eccad4e111579fd7f3bbf60b21ef4a16cea"}, {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"},
{file = "regex-2022.6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fdecb225d0f1d50d4b26ac423e0032e76d46a788b83b4e299a520717a47d968c"}, {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"},
{file = "regex-2022.6.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:be57f9c7b0b423c66c266a26ad143b2c5514997c05dd32ce7ca95c8b209c2288"}, {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"},
{file = "regex-2022.6.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ed657a07d8a47ef447224ea00478f1c7095065dfe70a89e7280e5f50a5725131"}, {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"},
{file = "regex-2022.6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:24908aefed23dd065b4a668c0b4ca04d56b7f09d8c8e89636cf6c24e64e67a1e"}, {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"},
{file = "regex-2022.6.2-cp310-cp310-win32.whl", hash = "sha256:775694cd0bb2c4accf2f1cdd007381b33ec8b59842736fe61bdbad45f2ac7427"}, {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"},
{file = "regex-2022.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:809bbbbbcf8258049b031d80932ba71627d2274029386f0452e9950bcfa2c6e8"}, {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"},
{file = "regex-2022.6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2b5d983eb0adf2049d41f95205bdc3de4e6cc2350e9c80d4409d3a75229de"}, {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"},
{file = "regex-2022.6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4c101746a8dac0401abefa716b357c546e61ea2e3d4a564a9db9eac57ccbce"}, {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"},
{file = "regex-2022.6.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:166ae7674d0a0e0f8044e7335ba86d0716c9d49465cff1b153f908e0470b8300"}, {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"},
{file = "regex-2022.6.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5eac5d8a8ac9ccf00805d02a968a36f5c967db6c7d2b747ab9ed782b3b3a28b"}, {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"},
{file = "regex-2022.6.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f57823f35b18d82b201c1b27ce4e55f88e79e81d9ca07b50ce625d33823e1439"}, {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"},
{file = "regex-2022.6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d42e3b7b23473729adbf76103e7df75f9167a5a80b1257ca30688352b4bb2dc"}, {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"},
{file = "regex-2022.6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2932e728bee0a634fe55ee54d598054a5a9ffe4cd2be21ba2b4b8e5f8064c2c"}, {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"},
{file = "regex-2022.6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:17764683ea01c2b8f103d99ae9de2473a74340df13ce306c49a721f0b1f0eb9e"}, {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"},
{file = "regex-2022.6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:2ac29b834100d2c171085ceba0d4a1e7046c434ddffc1434dbc7f9d59af1e945"}, {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"},
{file = "regex-2022.6.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:f43522fb5d676c99282ca4e2d41e8e2388427c0cf703db6b4a66e49b10b699a8"}, {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"},
{file = "regex-2022.6.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:9faa01818dad9111dbf2af26c6e3c45140ccbd1192c3a0981f196255bf7ec5e6"}, {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"},
{file = "regex-2022.6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:17443f99b8f255273731f915fdbfea4d78d809bb9c3aaf67b889039825d06515"}, {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"},
{file = "regex-2022.6.2-cp36-cp36m-win32.whl", hash = "sha256:4a5449adef907919d4ce7a1eab2e27d0211d1b255bf0b8f5dd330ad8707e0fc3"}, {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"},
{file = "regex-2022.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:4d206703a96a39763b5b45cf42645776f5553768ea7f3c2c1a39a4f59cafd4ba"}, {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"},
{file = "regex-2022.6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fcd7c432202bcb8b642c3f43d5bcafc5930d82fe5b2bf2c008162df258445c1d"}, {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"},
{file = "regex-2022.6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:186c5a4a4c40621f64d771038ede20fca6c61a9faa8178f9e305aaa0c2442a97"}, {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"},
{file = "regex-2022.6.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:047b2d1323a51190c01b6604f49fe09682a5c85d3c1b2c8b67c1cd68419ce3c4"}, {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"},
{file = "regex-2022.6.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30637e7fa4acfed444525b1ab9683f714be617862820578c9fd4e944d4d9ad1f"}, {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"},
{file = "regex-2022.6.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adafe6f2c6d86dbf3313866b61180530ca4dcd0c264932dc8fa1ffb10871d58"}, {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"},
{file = "regex-2022.6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67ae3601edf86e15ebe40885e5bfdd6002d34879070be15cf18fc0d80ea24fed"}, {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"},
{file = "regex-2022.6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:48dddddce0ea7e7c3e92c1e0c5a28c13ca4dc9cf7e996c706d00479652bff76c"}, {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"},
{file = "regex-2022.6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:68e5c641645351eb9eb12c465876e76b53717f99e9b92aea7a2dd645a87aa7aa"}, {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"},
{file = "regex-2022.6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8fd5f8ae42f789538bb634bdfd69b9aa357e76fdfd7ad720f32f8994c0d84f1e"}, {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"},
{file = "regex-2022.6.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:71988a76fcb68cc091e901fddbcac0f9ad9a475da222c47d3cf8db0876cb5344"}, {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"},
{file = "regex-2022.6.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:4b8838f70be3ce9e706df9d72f88a0aa7d4c1fea61488e06fdf292ccb70ad2be"}, {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"},
{file = "regex-2022.6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:663dca677bd3d2e2b5b7d0329e9f24247e6f38f3b740dd9a778a8ef41a76af41"}, {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"},
{file = "regex-2022.6.2-cp37-cp37m-win32.whl", hash = "sha256:24963f0b13cc63db336d8da2a533986419890d128c551baacd934c249d51a779"}, {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"},
{file = "regex-2022.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:ceff75127f828dfe7ceb17b94113ec2df4df274c4cd5533bb299cb099a18a8ca"}, {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"},
{file = "regex-2022.6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a6f2698cfa8340dfe4c0597782776b393ba2274fe4c079900c7c74f68752705"}, {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"},
{file = "regex-2022.6.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8a08ace913c4101f0dc0be605c108a3761842efd5f41a3005565ee5d169fb2b"}, {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"},
{file = "regex-2022.6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26dbe90b724efef7820c3cf4a0e5be7f130149f3d2762782e4e8ac2aea284a0b"}, {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"},
{file = "regex-2022.6.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5f759a1726b995dc896e86f17f9c0582b54eb4ead00ed5ef0b5b22260eaf2d0"}, {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"},
{file = "regex-2022.6.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1fc26bb3415e7aa7495c000a2c13bf08ce037775db98c1a3fac9ff04478b6930"}, {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"},
{file = "regex-2022.6.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52684da32d9003367dc1a1c07e059b9bbaf135ad0764cd47d8ac3dba2df109bc"}, {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"},
{file = "regex-2022.6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c1264eb40a71cf2bff43d6694ab7254438ca19ef330175060262b3c8dd3931a"}, {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"},
{file = "regex-2022.6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bc635ab319c9b515236bdf327530acda99be995f9d3b9f148ab1f60b2431e970"}, {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"},
{file = "regex-2022.6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:27624b490b5d8880f25dac67e1e2ea93dfef5300b98c6755f585799230d6c746"}, {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"},
{file = "regex-2022.6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:555f7596fd1f123f8c3a67974c01d6ef80b9769e04d660d6c1a7cc3e6cff7069"}, {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"},
{file = "regex-2022.6.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:933e72fbe1829cbd59da2bc51ccd73d73162f087f88521a87a8ec9cb0cf10fa8"}, {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"},
{file = "regex-2022.6.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:cff5c87e941292c97d11dc81bd20679f56a2830f0f0e32f75b8ed6e0eb40f704"}, {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"},
{file = "regex-2022.6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c757f3a27b6345de13ef3ca956aa805d7734ce68023e84d0fc74e1f09ce66f7a"}, {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"},
{file = "regex-2022.6.2-cp38-cp38-win32.whl", hash = "sha256:a58d21dd1a2d6b50ed091554ff85e448fce3fe33a4db8b55d0eba2ca957ed626"}, {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"},
{file = "regex-2022.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:495a4165172848503303ed05c9d0409428f789acc27050fe2cf0a4549188a7d5"}, {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"},
{file = "regex-2022.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1ab5cf7d09515548044e69d3a0ec77c63d7b9dfff4afc19653f638b992573126"}, {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"},
{file = "regex-2022.6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c1ea28f0ee6cbe4c0367c939b015d915aa9875f6e061ba1cf0796ca9a3010570"}, {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"},
{file = "regex-2022.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3de1ecf26ce85521bf73897828b6d0687cc6cf271fb6ff32ac63d26b21f5e764"}, {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"},
{file = "regex-2022.6.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7c7044aabdad2329974be2246babcc21d3ede852b3971a90fd8c2056c20360"}, {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"},
{file = "regex-2022.6.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:53d69d77e9cfe468b000314dd656be85bb9e96de088a64f75fe128dfe1bf30dd"}, {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"},
{file = "regex-2022.6.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c8d61883a38b1289fba9944a19a361875b5c0170b83cdcc95ea180247c1b7d3"}, {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"},
{file = "regex-2022.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5429202bef174a3760690d912e3a80060b323199a61cef6c6c29b30ce09fd17"}, {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"},
{file = "regex-2022.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e85b10280cf1e334a7c95629f6cbbfe30b815a4ea5f1e28d31f79eb92c2c3d93"}, {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"},
{file = "regex-2022.6.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c400dfed4137f32127ea4063447006d7153c974c680bf0fb1b724cce9f8567fc"}, {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"},
{file = "regex-2022.6.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7f648037c503985aed39f85088acab6f1eb6a0482d7c6c665a5712c9ad9eaefc"}, {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"},
{file = "regex-2022.6.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e7b2ff451f6c305b516281ec45425dd423223c8063218c5310d6f72a0a7a517c"}, {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"},
{file = "regex-2022.6.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:be456b4313a86be41706319c397c09d9fdd2e5cdfde208292a277b867e99e3d1"}, {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"},
{file = "regex-2022.6.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c3db393b21b53d7e1d3f881b64c29d886cbfdd3df007e31de68b329edbab7d02"}, {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"},
{file = "regex-2022.6.2-cp39-cp39-win32.whl", hash = "sha256:d70596f20a03cb5f935d6e4aad9170a490d88fc4633679bf00c652e9def4619e"}, {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"},
{file = "regex-2022.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:3b9b6289e03dbe6a6096880d8ac166cb23c38b4896ad235edee789d4e8697152"}, {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"},
{file = "regex-2022.6.2.tar.gz", hash = "sha256:f7b43acb2c46fb2cd506965b2d9cf4c5e64c9c612bac26c1187933c7296bf08c"}, {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"},
{file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"},
{file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"},
{file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"},
{file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"},
{file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"},
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"},
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"},
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"},
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"},
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"},
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"},
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"},
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"},
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"},
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"},
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"},
{file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"},
{file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"},
{file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"},
] ]
[[package]] [[package]]
@ -3130,17 +3164,6 @@ idna = "*"
requests = ">=2.1.0" requests = ">=2.1.0"
requests-file = ">=1.4" requests-file = ">=1.4"
[[package]]
name = "toml"
version = "0.10.1"
description = "Python Library for Tom's Obvious, Minimal Language"
optional = false
python-versions = "*"
files = [
{file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"},
{file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"},
]
[[package]] [[package]]
name = "tomli" name = "tomli"
version = "2.0.1" version = "2.0.1"
@ -3288,25 +3311,23 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.8.1" version = "20.21.1"
description = "Virtual Python Environment builder" description = "Virtual Python Environment builder"
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" python-versions = ">=3.7"
files = [ files = [
{file = "virtualenv-20.8.1-py2.py3-none-any.whl", hash = "sha256:10062e34c204b5e4ec5f62e6ef2473f8ba76513a9a617e873f1f8fb4a519d300"}, {file = "virtualenv-20.21.1-py3-none-any.whl", hash = "sha256:09ddbe1af0c8ed2bb4d6ed226b9e6415718ad18aef9fa0ba023d96b7a8356049"},
{file = "virtualenv-20.8.1.tar.gz", hash = "sha256:bcc17f0b3a29670dd777d6f0755a4c04f28815395bca279cdcb213b97199a6b8"}, {file = "virtualenv-20.21.1.tar.gz", hash = "sha256:4c104ccde994f8b108163cf9ba58f3d11511d9403de87fb9b4f52bf33dbc8668"},
] ]
[package.dependencies] [package.dependencies]
"backports.entry-points-selectable" = ">=1.0.4" distlib = ">=0.3.6,<1"
distlib = ">=0.3.1,<1" filelock = ">=3.4.1,<4"
filelock = ">=3.0.0,<4" platformdirs = ">=2.4,<4"
platformdirs = ">=2,<3"
six = ">=1.9.0,<2"
[package.extras] [package.extras]
docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)"]
[[package]] [[package]]
name = "watchtower" name = "watchtower"
@ -3605,21 +3626,6 @@ files = [
idna = ">=2.0" idna = ">=2.0"
multidict = ">=4.0" multidict = ">=4.0"
[[package]]
name = "zipp"
version = "3.2.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
optional = false
python-versions = ">=3.6"
files = [
{file = "zipp-3.2.0-py3-none-any.whl", hash = "sha256:43f4fa8d8bb313e65d8323a3952ef8756bf40f9a5c3ea7334be23ee4ec8278b6"},
{file = "zipp-3.2.0.tar.gz", hash = "sha256:b52f22895f4cfce194bc8172f3819ee8de7540aa6d873535a8668b730b8b411f"},
]
[package.extras]
docs = ["jaraco.packaging (>=3.2)", "rst.linker (>=1.9)", "sphinx"]
testing = ["func-timeout", "jaraco.itertools", "jaraco.test (>=3.2.0)", "pytest (>=3.5,!=3.7.3)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-flake8", "pytest-mypy"]
[[package]] [[package]]
name = "zope.event" name = "zope.event"
version = "4.5.0" version = "4.5.0"
@ -3698,4 +3704,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.10" python-versions = "^3.10"
content-hash = "01afc410d21eeac0a0ac7e8ef6eeb0a991cf4bc091c3351049263462e205ff63" content-hash = "22b9a61e9999a215aacb889b3790ee1a6840ce249aea2e3d16c6113243d5c126"

View file

@ -121,13 +121,13 @@ aiospamc = "0.10"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
pytest = "^7.0.0" pytest = "^7.0.0"
pytest-cov = "^3.0.0" pytest-cov = "^3.0.0"
pre-commit = "^2.17.0"
black = "^22.1.0" black = "^22.1.0"
djlint = "^1.3.0" djlint = "^1.3.0"
pylint = "^2.14.4" pylint = "^2.14.4"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
ruff = "^0.1.5" ruff = "^0.1.5"
pre-commit = "^3.8.0"
[build-system] [build-system]
requires = ["poetry>=0.12"] requires = ["poetry>=0.12"]

View file

@ -2,7 +2,7 @@
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label">{{ field.label }}</label> <label class="col-sm-2 col-form-label">{{ field.label }}</label>
<div class="col-sm-10"> <div class="col-sm-10">
{{ field(**kwargs)|safe }} {{ field(**kwargs) |safe }}
<small class="form-text text-muted">{{ field.description }}</small> <small class="form-text text-muted">{{ field.description }}</small>
{% if field.errors %} {% if field.errors %}

View file

@ -23,7 +23,7 @@
</tbody> </tbody>
</table> </table>
{%- endmacro %} {%- endmacro %}
{% macro list_mailboxes(mbox_count, mboxes) %} {% macro list_mailboxes(mbox_count, mboxes) %}
<h4> <h4>
{{ mbox_count }} Mailboxes found. {{ mbox_count }} Mailboxes found.
{% if mbox_count>10 %}Showing only the first 10.{% endif %} {% if mbox_count>10 %}Showing only the first 10.{% endif %}
@ -71,49 +71,29 @@
<td>{{ alias.id }}</td> <td>{{ alias.id }}</td>
<td>{{ alias.email }}</td> <td>{{ alias.email }}</td>
<td>{{ "Yes" if alias.verified else "No" }}</td> <td>{{ "Yes" if alias.verified else "No" }}</td>
<td> <td>{{ alias.created_at }}</td>
{{ alias.created_at }}
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% endmacro %} {% endmacro %}
{% macro show_deleted_alias(deleted_alias) -%} {% macro show_deleted_alias(deleted_alias) -%}
<h4> <h4>Deleted Alias {{ deleted_alias.email }} with ID {{ deleted_alias.id }}.</h4>
Deleted Alias {{ deleted_alias.email }} with ID {{ deleted_alias.id }}.
</h4>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th scope="col"> <th scope="col">Deleted Alias ID</th>
Deleted Alias ID <th scope="col">Email</th>
</th> <th scope="col">Deleted At</th>
<th scope="col"> <th scope="col">Reason</th>
Email
</th>
<th scope="col">
Deleted At
</th>
<th scope="col">
Reason
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td> <td>{{ deleted_alias.id }}</td>
{{ deleted_alias.id }} <td>{{ deleted_alias.email }}</td>
</td> <td>{{ deleted_alias.created_at }}</td>
<td> <td>{{ deleted_alias.reason }}</td>
{{ deleted_alias.email }}
</td>
<td>
{{ deleted_alias.created_at }}
</td>
<td>
{{ deleted_alias.reason }}
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -125,49 +105,23 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th scope="col"> <th scope="col">Deleted Alias ID</th>
Deleted Alias ID <th scope="col">Email</th>
</th> <th scope="col">Domain</th>
<th scope="col"> <th scope="col">Domain ID</th>
Email <th scope="col">Domain owner user ID</th>
</th> <th scope="col">Domain owner user email</th>
<th scope="col"> <th scope="col">Deleted At</th>
Domain
</th>
<th scope="col">
Domain ID
</th>
<th scope="col">
Domain owner user ID
</th>
<th scope="col">
Domain owner user email
</th>
<th scope="col">
Deleted At
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td> <td>{{ dom_deleted_alias.id }}</td>
{{ dom_deleted_alias.id }} <td>{{ dom_deleted_alias.email }}</td>
</td> <td>{{ dom_deleted_alias.domain.domain }}</td>
<td> <td>{{ dom_deleted_alias.domain.id }}</td>
{{ dom_deleted_alias.email }} <td>{{ dom_deleted_alias.domain.user_id }}</td>
</td> <td>{{ dom_deleted_alias.created_at }}</td>
<td>
{{ dom_deleted_alias.domain.domain }}
</td>
<td>
{{ dom_deleted_alias.domain.id }}
</td>
<td>
{{ dom_deleted_alias.domain.user_id }}
</td>
<td>
{{ dom_deleted_alias.created_at }}
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -178,73 +132,57 @@
<div class="border border-dark border-2 mt-1 mb-2 p-3"> <div class="border border-dark border-2 mt-1 mb-2 p-3">
<form method="post"> <form method="post">
<div class="form-group"> <div class="form-group">
<label for="email"> <label for="email">Email to search:</label>
Email to search:
</label>
<input type="text" <input type="text"
class="form-control" class="form-control"
name="email" name="email"
value="{{ email or '' }}"/> value="{{ email or '' }}" />
</div> </div>
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">Submit</button>
Submit
</button>
</form> </form>
</div> </div>
{% if no_match %} {% if no_match %}
<div class="border border-dark border-2 mt-1 mb-2 p-3 alert alert-warning" <div class="border border-dark border-2 mt-1 mb-2 p-3 alert alert-warning"
role="alert"> role="alert">No user, alias or mailbox found for {{ email }}</div>
No user, alias or mailbox found for {{ email }}
</div>
{% endif %} {% endif %}
{% if data.alias %} {% if data.alias %}
<div class="border border-dark border-2 mt-1 mb-2 p-3"> <div class="border border-dark border-2 mt-1 mb-2 p-3">
<h3 class="mb-3"> <h3 class="mb-3">Found Alias {{ data.alias.email }}</h3>
Found Alias {{ data.alias.email }}
</h3>
{{ list_alias(1,[data.alias]) }} {{ list_alias(1,[data.alias]) }}
{{ show_user(data.alias.user) }} {{ show_user(data.alias.user) }}
{{ list_mailboxes(helper.mailbox_count(data.alias.user), helper.mailbox_list(data.alias.user) ) }} {{ list_mailboxes(helper.mailbox_count(data.alias.user) , helper.mailbox_list(data.alias.user) ) }}
</div> </div>
{% endif %} {% endif %}
{% if data.user %} {% if data.user %}
<div class="border border-dark border-2 mt-1 mb-2 p-3"> <div class="border border-dark border-2 mt-1 mb-2 p-3">
<h3 class="mb-3"> <h3 class="mb-3">Found User {{ data.user.email }}</h3>
Found User {{ data.user.email }}
</h3>
{{ show_user(data.user) }} {{ show_user(data.user) }}
{{ list_mailboxes(helper.mailbox_count(data.user), helper.mailbox_list(data.user) ) }} {{ list_mailboxes(helper.mailbox_count(data.user) , helper.mailbox_list(data.user) ) }}
{{ list_alias(helper.alias_count(data.user),helper.alias_list(data.user)) }} {{ list_alias(helper.alias_count(data.user) ,helper.alias_list(data.user)) }}
</div> </div>
{% endif %} {% endif %}
{% if data.mailbox %} {% if data.mailbox %}
<div class="border border-dark mt-1 mb-2 p-3"> <div class="border border-dark mt-1 mb-2 p-3">
<h3 class="mb-3"> <h3 class="mb-3">Found Mailbox {{ data.mailbox.email }}</h3>
Found Mailbox {{ data.mailbox.email }} {{ list_mailboxes(1, [data.mailbox]) }}
</h3>
{{ list_mailboxes(1, [data.mailbox] ) }}
{{ show_user(data.mailbox.user) }} {{ show_user(data.mailbox.user) }}
</div> </div>
{% endif %} {% endif %}
{% if data.deleted_alias %} {% if data.deleted_alias %}
<div class="border border-dark mt-1 mb-2 p-3"> <div class="border border-dark mt-1 mb-2 p-3">
<h3 class="mb-3"> <h3 class="mb-3">Found DeletedAlias {{ data.deleted_alias.email }}</h3>
Found DeletedAlias {{ data.deleted_alias.email }}
</h3>
{{ show_deleted_alias(data.deleted_alias) }} {{ show_deleted_alias(data.deleted_alias) }}
</div> </div>
{% endif %} {% endif %}
{% if data.domain_deleted_alias %} {% if data.domain_deleted_alias %}
<div class="border border-dark mt-1 mb-2 p-3"> <div class="border border-dark mt-1 mb-2 p-3">
<h3 class="mb-3"> <h3 class="mb-3">Found DomainDeletedAlias {{ data.domain_deleted_alias.email }}</h3>
Found DomainDeletedAlias {{ data.domain_deleted_alias.email }}
</h3>
{{ show_domain_deleted_alias(data.domain_deleted_alias) }} {{ show_domain_deleted_alias(data.domain_deleted_alias) }}
</div> </div>
{% endif %} {% endif %}

View file

@ -11,11 +11,11 @@ Based on https://github.com/flask-admin/flask-admin/issues/974#issuecomment-1682
<input name="user_id" <input name="user_id"
class="form-control" class="form-control"
placeholder="User ID" placeholder="User ID"
aria-describedby="userID"/> aria-describedby="userID" />
<input name="to_address" <input name="to_address"
class="form-control" class="form-control"
placeholder="Specify an address to receive the newsletter for testing" placeholder="Specify an address to receive the newsletter for testing"
aria-describedby="Email address"/> aria-describedby="Email address" />
</li> </li>
{% endblock %} {% endblock %}
{% block tail %} {% block tail %}

View file

@ -7,7 +7,7 @@
<div class="text-center text-muted small mt-4"> <div class="text-center text-muted small mt-4">
Ask for another activation email? Ask for another activation email?
<a href="{{ url_for('auth.resend_activation') }}" style="color: #4d21ff">Resend</a> <a href="{{ url_for("auth.resend_activation") }}" style="color: #4d21ff">Resend</a>
</div> </div>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -13,7 +13,7 @@
</div> </div>
<div class="text-center"> <div class="text-center">
Please go to Please go to
<a href="{{ url_for('dashboard.setting') }}">settings</a> <a href="{{ url_for("dashboard.setting") }}">settings</a>
page to re-send the confirmation email. page to re-send the confirmation email.
</div> </div>
</div> </div>

View file

@ -33,7 +33,7 @@
<div class="text-muted mt-5" style="margin-top: 1em;"> <div class="text-muted mt-5" style="margin-top: 1em;">
Don't have your key with you? Don't have your key with you?
<br /> <br />
<a href="{{ url_for('auth.mfa') }}">Verify by One-Time Password</a> <a href="{{ url_for("auth.mfa") }}">Verify by One-Time Password</a>
</div> </div>
{% endif %} {% endif %}
<hr /> <hr />

View file

@ -20,7 +20,7 @@
</form> </form>
<div class="text-center text-muted"> <div class="text-center text-muted">
Forget it, Forget it,
<a href="{{ url_for('auth.login') }}">send me back</a> <a href="{{ url_for("auth.login") }}">send me back</a>
to the sign in screen. to the sign in screen.
</div> </div>
{% endblock %} {% endblock %}

View file

@ -7,7 +7,7 @@
<div class="text-center text-muted small mb-4"> <div class="text-center text-muted small mb-4">
You haven't received the activation email? You haven't received the activation email?
<a href="{{ url_for('auth.resend_activation') }}">Resend</a> <a href="{{ url_for("auth.resend_activation") }}">Resend</a>
</div> </div>
{% endif %} {% endif %}
<div class="card" style="border-radius: 2%"> <div class="card" style="border-radius: 2%">
@ -25,7 +25,7 @@
{{ form.password(class="form-control", type="password") }} {{ form.password(class="form-control", type="password") }}
{{ render_field_errors(form.password) }} {{ render_field_errors(form.password) }}
<div class="text-muted"> <div class="text-muted">
<a href="{{ url_for('auth.forgot_password') }}" class="small">I forgot my password</a> <a href="{{ url_for("auth.forgot_password") }}" class="small">I forgot my password</a>
</div> </div>
</div> </div>
<div class="form-footer"> <div class="form-footer">
@ -57,6 +57,6 @@
</div> </div>
<div class="text-center text-muted mt-2"> <div class="text-center text-muted mt-2">
Don't have an account yet? Don't have an account yet?
<a href="{{ url_for('auth.register') }}">Sign up</a> <a href="{{ url_for("auth.register") }}">Sign up</a>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -30,7 +30,7 @@
<div class="text-muted mt-5" style="margin-top: 1em;"> <div class="text-muted mt-5" style="margin-top: 1em;">
Having trouble with your authenticator? Having trouble with your authenticator?
<br /> <br />
<a href="{{ url_for('auth.fido') }}"> <a href="{{ url_for("auth.fido") }}">
Verify by your security Verify by your security
key key
</a> </a>

View file

@ -27,7 +27,7 @@
<!-- TODO: add terms <!-- TODO: add terms
<div class="form-group"> <div class="form-group">
<label class="custom-control custom-checkbox"> <label class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input"/> <input type="checkbox" class="custom-control-input" />
<span class="custom-control-label">Agree the <a href="terms.html">terms and policy</a></span> <span class="custom-control-label">Agree the <a href="terms.html">terms and policy</a></span>
</label> </label>
</div> </div>
@ -69,6 +69,6 @@
</form> </form>
<div class="text-center text-muted mb-6"> <div class="text-center text-muted mb-6">
Already have account? Already have account?
<a href="{{ url_for('auth.login') }}">Sign in</a> <a href="{{ url_for("auth.login") }}">Sign in</a>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -19,6 +19,6 @@
</form> </form>
<div class="text-center text-muted"> <div class="text-center text-muted">
Don't have account yet? Don't have account yet?
<a href="{{ url_for('auth.register') }}">Sign up</a> <a href="{{ url_for("auth.register") }}">Sign up</a>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -29,7 +29,9 @@
{% endif %} {% endif %}
</div> </div>
<div class="text-center p-3" <div class="text-center p-3"
style="font-size: 12px; font-weight: 300; margin: auto"> style="font-size: 12px;
font-weight: 300;
margin: auto">
<span class="badge badge-warning">Warning</span> <span class="badge badge-warning">Warning</span>
Please note that social login is now <b>deprecated</b>. Please note that social login is now <b>deprecated</b>.
<br /> <br />
@ -39,8 +41,8 @@
</div> </div>
</div> </div>
<div class="text-center text-muted mt-2"> <div class="text-center text-muted mt-2">
<a href="{{ url_for('auth.register') }}">Sign up</a> <a href="{{ url_for("auth.register") }}">Sign up</a>
/ /
<a href="{{ url_for('auth.login') }}">Login</a> <a href="{{ url_for("auth.login") }}">Login</a>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,18 +1,18 @@
{% from "_formhelpers.html" import render_field, render_field_errors %} {% from "_formhelpers.html" import render_field, render_field_errors %}
<!doctype html> <!DOCTYPE html>
<html lang="en" <html lang="en"
dir="ltr" dir="ltr"
data-theme="{%- if request.cookies.get('dark-mode') == 'true' -%} dark{%- endif -%}"> data-theme="{%- if request.cookies.get('dark-mode') == 'true' -%} dark{%- endif -%}">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" <meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/> content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta http-equiv="Content-Language" content="en" /> <meta http-equiv="Content-Language" content="en" />
<meta name="msapplication-TileColor" content="#2d89ef" /> <meta name="msapplication-TileColor" content="#2d89ef" />
<meta name="theme-color" content="#4188c9" /> <meta name="theme-color" content="#4188c9" />
<meta name="apple-mobile-web-app-status-bar-style" <meta name="apple-mobile-web-app-status-bar-style"
content="black-translucent"/> content="black-translucent" />
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<meta name="HandheldFriendly" content="True" /> <meta name="HandheldFriendly" content="True" />
@ -23,7 +23,7 @@
<!-- Yandex --> <!-- Yandex -->
<meta name="yandex-verification" content="c9e5d4d68bc983a1" /> <meta name="yandex-verification" content="c9e5d4d68bc983a1" />
<meta name="description" <meta name="description"
content="Protect your email address with email ALIAS. Create a different email alias for each website. No more phishing, or spam."/> content="Protect your email address with email ALIAS. Create a different email alias for each website. No more phishing, or spam." />
<link rel="icon" href="/static/favicon.ico" type="image/x-icon" /> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" /> <link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" />
<link rel="canonical" href="{{ CANONICAL_URL }}" /> <link rel="canonical" href="{{ CANONICAL_URL }}" />
@ -32,7 +32,7 @@
| SimpleLogin | SimpleLogin
</title> </title>
<link rel="stylesheet" <link rel="stylesheet"
href="{{ url_for('static', filename='node_modules/font-awesome/css/font-awesome.css') }}"/> href="{{ url_for('static', filename='node_modules/font-awesome/css/font-awesome.css') }}" />
<!-- Dashboard Core --> <!-- Dashboard Core -->
<link href="/static/assets/css/dashboard.css" rel="stylesheet" /> <link href="/static/assets/css/dashboard.css" rel="stylesheet" />
<!-- Tabler JS --> <!-- Tabler JS -->
@ -51,19 +51,19 @@
<!-- IntroJS --> <!-- IntroJS -->
<link rel="stylesheet" <link rel="stylesheet"
type="text/css" type="text/css"
href="{{ url_for('static', filename='node_modules/intro.js/minified/introjs.min.css') }}"/> href="{{ url_for('static', filename='node_modules/intro.js/minified/introjs.min.css') }}" />
<script src="{{ url_for('static', filename='node_modules/intro.js/minified/intro.min.js') }}"></script> <script src="{{ url_for('static', filename='node_modules/intro.js/minified/intro.min.js') }}"></script>
<!-- Sentry --> <!-- Sentry -->
<script src="{{ url_for('static', filename='node_modules/@sentry/browser/build/bundle.min.js') }}"></script> <script src="{{ url_for('static', filename='node_modules/@sentry/browser/build/bundle.min.js') }}"></script>
<link rel="stylesheet" href="/static/vendor/bootstrap-social.min.css" /> <link rel="stylesheet" href="/static/vendor/bootstrap-social.min.css" />
<!-- Toastr library --> <!-- Toastr library -->
<link rel="stylesheet" <link rel="stylesheet"
href="{{ url_for('static', filename='node_modules/toastr/build/toastr.min.css') }}"/> href="{{ url_for('static', filename='node_modules/toastr/build/toastr.min.css') }}" />
<script src="{{ url_for('static', filename='node_modules/toastr/build/toastr.min.js') }}"></script> <script src="{{ url_for('static', filename='node_modules/toastr/build/toastr.min.js') }}"></script>
<script src="{{ url_for('static', filename='node_modules/bootbox/dist/bootbox.min.js') }}"></script> <script src="{{ url_for('static', filename='node_modules/bootbox/dist/bootbox.min.js') }}"></script>
<!-- Multiple-select library --> <!-- Multiple-select library -->
<link rel="stylesheet" <link rel="stylesheet"
href="{{ url_for('static', filename='node_modules/multiple-select/dist/multiple-select.min.css') }}"/> href="{{ url_for('static', filename='node_modules/multiple-select/dist/multiple-select.min.css') }}" />
<script src="{{ url_for('static', filename='node_modules/multiple-select/dist/multiple-select.min.js') }}"></script> <script src="{{ url_for('static', filename='node_modules/multiple-select/dist/multiple-select.min.js') }}"></script>
<!-- Parseley library --> <!-- Parseley library -->
<script src="{{ url_for('static', filename='node_modules/parsleyjs/dist/parsley.min.js') }}"></script> <script src="{{ url_for('static', filename='node_modules/parsleyjs/dist/parsley.min.js') }}"></script>
@ -75,10 +75,10 @@
<script async defer data-domain=”{{ PLAUSIBLE_DOMAIN }} src=”{{ PLAUSIBLE_HOST }}/js/plausible.outbound-links.js></script> <script async defer data-domain=”{{ PLAUSIBLE_DOMAIN }} src=”{{ PLAUSIBLE_HOST }}/js/plausible.outbound-links.js></script>
{% endif %} {% endif %}
<link rel="stylesheet" <link rel="stylesheet"
href="{{ url_for('static', filename='darkmode.css') }}?v={{ VERSION }}"/> href="{{ url_for('static', filename='darkmode.css') }}?v={{ VERSION }}" />
<link rel="stylesheet" <link rel="stylesheet"
type="text/css" type="text/css"
href="/static/style.css?v={{ VERSION }}"/> href="/static/style.css?v={{ VERSION }}" />
<script src="{{ url_for('static', filename='js/theme.js') }}"></script> <script src="{{ url_for('static', filename='js/theme.js') }}"></script>
<script>toastr.options.closeButton = true;</script> <script>toastr.options.closeButton = true;</script>
<!-- For additional head --> <!-- For additional head -->

View file

@ -33,7 +33,7 @@
This email address is used to log in to SimpleLogin. This email address is used to log in to SimpleLogin.
<br /> <br />
If you want to change the mailbox that emails are forwarded to, use the If you want to change the mailbox that emails are forwarded to, use the
<a href="{{ url_for('dashboard.mailbox_route') }}"> <a href="{{ url_for("dashboard.mailbox_route") }}">
<i class="fe fe-inbox"></i> Mailboxes page <i class="fe fe-inbox"></i> Mailboxes page
</a> </a>
instead. instead.
@ -50,14 +50,14 @@
<div class="mt-2"> <div class="mt-2">
<span class="text-danger float-left">Pending email change: {{ pending_email }}</span> <span class="text-danger float-left">Pending email change: {{ pending_email }}</span>
<form method="POST" <form method="POST"
action="{{ url_for('dashboard.resend_email_change') }}" action="{{ url_for("dashboard.resend_email_change") }}"
class="float-left ml-2"> class="float-left ml-2">
{{ change_email_form.csrf_token }} {{ change_email_form.csrf_token }}
<a onclick="this.closest('form').submit()" <a onclick="this.closest('form').submit()"
class="btn btn-secondary btn-sm">Resend confirmation email</a> class="btn btn-secondary btn-sm">Resend confirmation email</a>
</form> </form>
<form method="POST" <form method="POST"
action="{{ url_for('dashboard.cancel_email_change') }}" action="{{ url_for("dashboard.cancel_email_change") }}"
class="float-left ml-2"> class="float-left ml-2">
{{ change_email_form.csrf_token }} {{ change_email_form.csrf_token }}
<a onclick="this.closest('form').submit()" <a onclick="this.closest('form').submit()"
@ -91,10 +91,10 @@
</div> </div>
{% if not current_user.enable_otp %} {% if not current_user.enable_otp %}
<a href="{{ url_for('dashboard.mfa_setup') }}" <a href="{{ url_for("dashboard.mfa_setup") }}"
class="btn btn-outline-primary">Setup TOTP</a> class="btn btn-outline-primary">Setup TOTP</a>
{% else %} {% else %}
<a href="{{ url_for('dashboard.mfa_cancel') }}" <a href="{{ url_for("dashboard.mfa_cancel") }}"
class="btn btn-outline-danger">Disable TOTP</a> class="btn btn-outline-danger">Disable TOTP</a>
{% endif %} {% endif %}
</div> </div>
@ -111,10 +111,10 @@
</div> </div>
{% if current_user.fido_uuid is none %} {% if current_user.fido_uuid is none %}
<a href="{{ url_for('dashboard.fido_setup') }}" <a href="{{ url_for("dashboard.fido_setup") }}"
class="btn btn-outline-primary">Setup WebAuthn</a> class="btn btn-outline-primary">Setup WebAuthn</a>
{% else %} {% else %}
<a href="{{ url_for('dashboard.fido_manage') }}" <a href="{{ url_for("dashboard.fido_manage") }}"
class="btn btn-outline-info">Manage WebAuthn</a> class="btn btn-outline-info">Manage WebAuthn</a>
{% endif %} {% endif %}
</div> </div>
@ -146,7 +146,7 @@
<div class="card-body"> <div class="card-body">
<div class="card-title">Account Deletion</div> <div class="card-title">Account Deletion</div>
<div class="mb-3">If SimpleLogin isn't the right fit for you, you can simply delete your account.</div> <div class="mb-3">If SimpleLogin isn't the right fit for you, you can simply delete your account.</div>
<a href="{{ url_for('dashboard.delete_account') }}" <a href="{{ url_for("dashboard.delete_account") }}"
class="btn btn-outline-danger">Delete account</a> class="btn btn-outline-danger">Delete account</a>
</div> </div>
</div> </div>

View file

@ -27,7 +27,7 @@
<br /> <br />
<img src="/static/images/reverse-alias.svg" <img src="/static/images/reverse-alias.svg"
style="border: 1px solid" style="border: 1px solid"
class="my-2 img-fluid"/> class="my-2 img-fluid" />
</p> </p>
<p>This might seem like "magic" but trust us, only the first time is a bit awkward.</p> <p>This might seem like "magic" but trust us, only the first time is a bit awkward.</p>
<p> <p>
@ -75,9 +75,7 @@
{% else %} {% else %}
<button disabled <button disabled
title="Upgrade to premium to create reverse-aliases" title="Upgrade to premium to create reverse-aliases"
class="btn btn-primary mt-2"> class="btn btn-primary mt-2">Create reverse-alias</button>
Create reverse-alias
</button>
{% endif %} {% endif %}
</form> </form>
</div> </div>
@ -98,9 +96,7 @@
{% if highlight_contact_id %} {% if highlight_contact_id %}
<a href="{{ url_for("dashboard.alias_contact_manager", alias_id=alias.id, highlight_contact_id=highlight_contact_id) }}" <a href="{{ url_for("dashboard.alias_contact_manager", alias_id=alias.id, highlight_contact_id=highlight_contact_id) }}"
class="btn btn-light"> class="btn btn-light">Reset</a>
Reset
</a>
{% else %} {% else %}
<a href="{{ url_for("dashboard.alias_contact_manager", alias_id=alias.id) }}" <a href="{{ url_for("dashboard.alias_contact_manager", alias_id=alias.id) }}"
class="btn btn-light">Reset</a> class="btn btn-light">Reset</a>
@ -114,7 +110,7 @@
{% set contact = contact_info.contact %} {% set contact = contact_info.contact %}
<div class="col-md-6"> <div class="col-md-6">
<div class="my-2 p-2 card {% if contact.id == highlight_contact_id %} highlight-row{% endif %}"> <div class="my-2 p-2 card {% if contact.id == highlight_contact_id %}highlight-row{% endif %}">
<div class="mb-2 row"> <div class="mb-2 row">
<div class="col"> <div class="col">
<span class="font-weight-bold">{{ contact.website_email }}</span> <span class="font-weight-bold">{{ contact.website_email }}</span>
@ -139,15 +135,11 @@
target="_blank" target="_blank"
data-toggle="tooltip" data-toggle="tooltip"
title="You can click on this to open your email client. Or use the copy button 👉" title="You can click on this to open your email client. Or use the copy button 👉"
class="font-weight-bold"> class="font-weight-bold">*************************</a>
*************************
</a>
<span class="clipboard btn btn-sm btn-success copy-btn" <span class="clipboard btn btn-sm btn-success copy-btn"
data-toggle="tooltip" data-toggle="tooltip"
title="Copy the reverse-alias to clipboard" title="Copy the reverse-alias to clipboard"
data-clipboard-text="{{ contact.website_send_to() }}"> data-clipboard-text="{{ contact.website_send_to() }}">Copy reverse-alias</span>
Copy reverse-alias
</span>
</span> </span>
</div> </div>
<div class="mb-2 text-muted small-text"> <div class="mb-2 text-muted small-text">
@ -207,14 +199,12 @@
<nav aria-label="Contact navigation"> <nav aria-label="Contact navigation">
<ul class="pagination"> <ul class="pagination">
<li class="page-item"> <li class="page-item">
<a class="btn btn-outline-secondary {% if page == 0 %}disabled{% endif %}" <a class="btn btn-outline-secondary {% if page == 0 %}disabled{% endif %}" href="{{ url_for('dashboard.alias_contact_manager', alias_id=alias.id, page=page-1) }}">
href="{{ url_for('dashboard.alias_contact_manager', alias_id=alias.id, page=page-1) }}">
Previous Previous
</a> </a>
</li> </li>
<li class="page-item"> <li class="page-item">
<a class="btn btn-outline-secondary {% if last_page %}disabled{% endif %}" <a class="btn btn-outline-secondary {% if last_page %}disabled{% endif %}" href="{{ url_for('dashboard.alias_contact_manager', alias_id=alias.id, page=page+1) }}">
href="{{ url_for('dashboard.alias_contact_manager', alias_id=alias.id, page=page+1) }}">
Next Next
</a> </a>
</li> </li>

View file

@ -13,7 +13,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Total</div> <div class="subheader">Total</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">Last 14 days</div> style="order: 2;
margin-left: auto;
font-size: .8rem">Last 14 days</div>
</div> </div>
<div class="h1 m-0">{{ total }}</div> <div class="h1 m-0">{{ total }}</div>
</div> </div>
@ -25,7 +27,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Forwarded</div> <div class="subheader">Forwarded</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">Last 14 days</div> style="order: 2;
margin-left: auto;
font-size: .8rem">Last 14 days</div>
</div> </div>
<div class="h1 m-0">{{ email_forwarded }}</div> <div class="h1 m-0">{{ email_forwarded }}</div>
</div> </div>
@ -37,7 +41,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Replies/Sent</div> <div class="subheader">Replies/Sent</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">Last 14 days</div> style="order: 2;
margin-left: auto;
font-size: .8rem">Last 14 days</div>
</div> </div>
<div class="h1 m-0">{{ email_replied }}</div> <div class="h1 m-0">{{ email_replied }}</div>
</div> </div>
@ -49,7 +55,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Blocked</div> <div class="subheader">Blocked</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">Last 14 days</div> style="order: 2;
margin-left: auto;
font-size: .8rem">Last 14 days</div>
</div> </div>
<div class="h1 m-0">{{ email_blocked }}</div> <div class="h1 m-0">{{ email_blocked }}</div>
</div> </div>
@ -111,14 +119,12 @@
<nav aria-label="Alias log navigation"> <nav aria-label="Alias log navigation">
<ul class="pagination"> <ul class="pagination">
<li class="page-item"> <li class="page-item">
<a class="btn btn-outline-secondary {% if page_id == 0 %}disabled{% endif %}" <a class="btn btn-outline-secondary {% if page_id == 0 %}disabled{% endif %}" href="{{ url_for('dashboard.alias_log', alias_id=alias_id, page_id=page_id-1) }}">
href="{{ url_for('dashboard.alias_log', alias_id=alias_id, page_id=page_id-1) }}">
Previous Previous
</a> </a>
</li> </li>
<li class="page-item"> <li class="page-item">
<a class="btn btn-outline-secondary {% if last_page %}disabled{% endif %}" <a class="btn btn-outline-secondary {% if last_page %}disabled{% endif %}" href="{{ url_for('dashboard.alias_log', alias_id=alias_id, page_id=page_id+1) }}">
href="{{ url_for('dashboard.alias_log', alias_id=alias_id, page_id=page_id+1) }}">
Next Next
</a> </a>
</li> </li>

View file

@ -15,10 +15,7 @@
<select data-width="100%" class="mailbox-select" multiple name="mailbox_ids"> <select data-width="100%" class="mailbox-select" multiple name="mailbox_ids">
{% for mailbox in mailboxes %} {% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" <option value="{{ mailbox.id }}" {% if mailbox.id == current_user.default_mailbox_id %}selected{% endif %}>{{ mailbox.email }}</option>
{% if mailbox.id == current_user.default_mailbox_id %} selected{% endif %}>
{{ mailbox.email }}
</option>
{% endfor %} {% endfor %}
</select> </select>
<button class="btn btn-success mt-2">Confirm</button> <button class="btn btn-success mt-2">Confirm</button>

View file

@ -16,9 +16,7 @@
<em data-toggle="tooltip" <em data-toggle="tooltip"
title="Click to copy" title="Click to copy"
class="clipboard" class="clipboard"
data-clipboard-text="{{ alias_transfer_url }}"> data-clipboard-text="{{ alias_transfer_url }}">{{ alias_transfer_url }}</em>
{{ alias_transfer_url }}
</em>
<p class="mt-5"> <p class="mt-5">
Please copy the transfer URL. <strong>We won't be able to display it again</strong>. If you need to access it again you can generate a new URL. Please copy the transfer URL. <strong>We won't be able to display it again</strong>. If you need to access it again you can generate a new URL.
</p> </p>

View file

@ -22,7 +22,7 @@
<br /> <br />
The period left in the current subscription isn't taken into account. The period left in the current subscription isn't taken into account.
<br /> <br />
<a href="{{ url_for('dashboard.pricing') }}" <a href="{{ url_for("dashboard.pricing") }}"
class="btn btn-primary mt-2">Re-subscribe</a> class="btn btn-primary mt-2">Re-subscribe</a>
</p> </p>
{% else %} {% else %}

View file

@ -43,12 +43,14 @@
{% endif %} {% endif %}
<div class="form-group"> <div class="form-group">
<label class="form-label">PGP Public Key</label> <label class="form-label">PGP Public Key</label>
<textarea name="pgp" {% if not current_user.is_premium() %} disabled {% endif %} class="form-control" rows=10 id="pgp-public-key" placeholder="(Drag and drop or paste your pgp public key here)&#10;-----BEGIN PGP PUBLIC KEY BLOCK-----">{{ contact.pgp_public_key or "" }}</textarea> <textarea name="pgp"
{% if not current_user.is_premium() %}disabled{% endif %}
class="form-control"
rows="10"
id="pgp-public-key"
placeholder="(Drag and drop or paste your pgp public key here)&#10;-----BEGIN PGP PUBLIC KEY BLOCK-----">{{ contact.pgp_public_key or "" }}</textarea>
</div> </div>
<button class="btn btn-primary" name="action" {% if not current_user.is_premium() %} <button class="btn btn-primary" name="action" {% if not current_user.is_premium() %}disabled{% endif %} value="save">Save</button>
disabled {% endif %} value="save">
Save
</button>
{% if contact.pgp_finger_print %} {% if contact.pgp_finger_print %}
<button class="btn btn-danger float-right" name="action" value="remove">Remove</button> <button class="btn btn-danger float-right" name="action" value="remove">Remove</button>

View file

@ -74,10 +74,7 @@
required> required>
{% for mailbox in mailboxes %} {% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" <option value="{{ mailbox.id }}" {% if mailbox.id == current_user.default_mailbox_id %}selected{% endif %}>{{ mailbox.email }}</option>
{% if mailbox.id == current_user.default_mailbox_id %} selected{% endif %}>
{{ mailbox.email }}
</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="small-text">The mailbox(es) that owns this alias.</div> <div class="small-text">The mailbox(es) that owns this alias.</div>
@ -102,7 +99,6 @@
</div> </div>
{% endblock %} {% endblock %}
{% block script %} {% block script %}
<script> <script>
$('.mailbox-select').multipleSelect(); $('.mailbox-select').multipleSelect();

View file

@ -30,9 +30,7 @@
</a> </a>
</div> </div>
{% endif %} {% endif %}
<div class="alert alert-primary collapse {% if not custom_domains %} show{% endif %}" <div class="alert alert-primary collapse {% if not custom_domains %}show{% endif %}" id="howtouse" role="alert">
id="howtouse"
role="alert">
By adding your domain, you can create aliases like <b>hi@my-domain.com</b> By adding your domain, you can create aliases like <b>hi@my-domain.com</b>
<br /> <br />
You can also enable <b>catch-all</b> to create aliases on-the-fly: You can also enable <b>catch-all</b> to create aliases on-the-fly:
@ -50,18 +48,14 @@
{% if custom_domain.ownership_verified and not custom_domain.verified %} {% if custom_domain.ownership_verified and not custom_domain.verified %}
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id, _anchor='dns-setup') }}" <a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id, _anchor='dns-setup') }}"
class="btn btn-info btn-sm"> class="btn btn-info btn-sm">Ownership verified. Setup the DNS</a>
Ownership verified. Setup the DNS
</a>
{% elif custom_domain.ownership_verified and custom_domain.verified %} {% elif custom_domain.ownership_verified and custom_domain.verified %}
<span class="badge badge-success">Domain ready</span> <span class="badge badge-success">Domain ready</span>
<!-- custom_domain.ownership_verified is False --> <!-- custom_domain.ownership_verified is False -->
{% else %} {% else %}
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id, _anchor='ownership-form') }}" <a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id, _anchor='ownership-form') }}"
class="btn btn-warning btn-sm" class="btn btn-warning btn-sm"
role="button"> role="button">Verify domain ownership</a>
Verify domain ownership
</a>
{% endif %} {% endif %}
</h5> </h5>
<h6 class="card-subtitle mb-4 text-muted"> <h6 class="card-subtitle mb-4 text-muted">

View file

@ -22,9 +22,7 @@
<div class="alert alert-danger" role="alert">This feature is only available in premium plan.</div> <div class="alert alert-danger" role="alert">This feature is only available in premium plan.</div>
{% endif %} {% endif %}
<div class="alert alert-primary collapse {% if not dirs %} show{% endif %}" <div class="alert alert-primary collapse {% if not dirs %}show{% endif %}" id="howtouse" role="alert">
id="howtouse"
role="alert">
<div> <div>
Directory allows you to create aliases <b>on the fly</b>. Directory allows you to create aliases <b>on the fly</b>.
</div> </div>
@ -68,10 +66,10 @@
<form method="post"> <form method="post">
{{ toggle_dir_form.csrf_token }} {{ toggle_dir_form.csrf_token }}
<input type="hidden" name="form-name" value="toggle-directory"> <input type="hidden" name="form-name" value="toggle-directory">
{{ toggle_dir_form.directory_id( type="hidden", value=dir.id) }} {{ toggle_dir_form.directory_id(type="hidden", value=dir.id) }}
<label class="custom-switch cursor" style="padding-left: 1rem" data-toggle="tooltip" {% if dir.disabled %} <label class="custom-switch cursor" style="padding-left: 1rem" data-toggle="tooltip" {% if dir.disabled %}
title="Enable directory on-the-fly alias creation" {% else %} title="Disable directory on-the-fly alias creation" {% endif %}> title="Enable directory on-the-fly alias creation" {% else %} title="Disable directory on-the-fly alias creation" {% endif %}>
{{ toggle_dir_form.directory_enabled( class="custom-switch-input", checked=(not dir.disabled) ) }} {{ toggle_dir_form.directory_enabled(class="custom-switch-input", checked=(not dir.disabled) ) }}
<span class="custom-switch-indicator"></span> <span class="custom-switch-indicator"></span>
</label> </label>
</form> </form>
@ -91,11 +89,11 @@
data-toggle="tooltip" data-toggle="tooltip"
title="Aliases created with this directory are automatically owned by these mailboxes"></i> title="Aliases created with this directory are automatically owned by these mailboxes"></i>
<br /> <br />
{% set dir_mailboxes=dir.mailboxes %} {% set dir_mailboxes = dir.mailboxes %}
<form method="post" class="mt-2"> <form method="post" class="mt-2">
{{ update_dir_form.csrf_token }} {{ update_dir_form.csrf_token }}
<input type="hidden" name="form-name" value="update"> <input type="hidden" name="form-name" value="update">
{{ update_dir_form.directory_id( type="hidden", value=dir.id) }} {{ update_dir_form.directory_id(type="hidden", value=dir.id) }}
<select data-width="100%" <select data-width="100%"
required required
class="mailbox-select" class="mailbox-select"
@ -103,10 +101,7 @@
name="mailbox_ids"> name="mailbox_ids">
{% for mailbox in mailboxes %} {% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" <option value="{{ mailbox.id }}" {% if mailbox in dir_mailboxes %}selected{% endif %}>{{ mailbox.email }}</option>
{% if mailbox in dir_mailboxes %} selected{% endif %}>
{{ mailbox.email }}
</option>
{% endfor %} {% endfor %}
</select> </select>
<button class="mt-2 btn btn-outline-primary btn-sm">Update</button> <button class="mt-2 btn btn-outline-primary btn-sm">Update</button>
@ -119,7 +114,7 @@
<form method="post"> <form method="post">
{{ delete_dir_form.csrf_token }} {{ delete_dir_form.csrf_token }}
<input type="hidden" name="form-name" value="delete"> <input type="hidden" name="form-name" value="delete">
{{ delete_dir_form.directory_id( type="hidden", value=dir.id) }} {{ delete_dir_form.directory_id(type="hidden", value=dir.id) }}
<span class="card-link btn btn-link float-right text-danger delete-dir">Delete</span> <span class="card-link btn btn-link float-right text-danger delete-dir">Delete</span>
</form> </form>
</div> </div>
@ -129,7 +124,7 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
<div class="row {% if current_user.directory_quota <= 0 %} disabled-content{% endif %}"> <div class="row {% if current_user.directory_quota <= 0 %}disabled-content{% endif %}">
<div class="col"> <div class="col">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
@ -139,8 +134,8 @@
<h2 class="h4 mb-1">New Directory</h2> <h2 class="h4 mb-1">New Directory</h2>
<div class="small-text mb-4">You can create up to {{ current_user.directory_quota }} directories.</div> <div class="small-text mb-4">You can create up to {{ current_user.directory_quota }} directories.</div>
{{ new_dir_form.name(class="form-control", placeholder="my-directory", {{ new_dir_form.name(class="form-control", placeholder="my-directory",
pattern="[0-9a-z-_]{3,}", pattern="[0-9a-z-_]{3,}",
title="Only letter, number, dash (-), underscore (_) can be used. Directory name must be at least 3 characters.") }} title="Only letter, number, dash (-), underscore (_) can be used. Directory name must be at least 3 characters.") }}
{{ render_field_errors(new_dir_form.name) }} {{ render_field_errors(new_dir_form.name) }}
<div class="small-text"> <div class="small-text">
Directory name must be at least 3 characters. Directory name must be at least 3 characters.
@ -156,10 +151,7 @@
<select data-width="100%" class="mailbox-select" multiple name="mailbox_ids"> <select data-width="100%" class="mailbox-select" multiple name="mailbox_ids">
{% for mailbox in mailboxes %} {% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" <option value="{{ mailbox.id }}" {% if mailbox.id == current_user.default_mailbox_id %}selected{% endif %}>{{ mailbox.email }}</option>
{% if mailbox.id == current_user.default_mailbox_id %} selected{% endif %}>
{{ mailbox.email }}
</option>
{% endfor %} {% endfor %}
</select> </select>
<button id="btn-create-directory" class="btn btn-primary mt-2">Create</button> <button id="btn-create-directory" class="btn btn-primary mt-2">Create</button>

View file

@ -13,7 +13,8 @@
<div class="alert alert-warning mt-3">Rules are ineffective when catch-all is enabled.</div> <div class="alert alert-warning mt-3">Rules are ineffective when catch-all is enabled.</div>
{% endif %} {% endif %}
<div class="{% if custom_domain.catch_all %} disabled-content{% endif %}"> <div class="{% if custom_domain.catch_all %}
disabled-content{% endif %}">
<div class="mt-3 mb-2"> <div class="mt-3 mb-2">
For a greater control than a simple catch-all, you can define a set of <b>rules</b> to auto create aliases. For a greater control than a simple catch-all, you can define a set of <b>rules</b> to auto create aliases.
<br /> <br />
@ -60,8 +61,7 @@
<div class="form-group"> <div class="form-group">
<label>Regex</label> <label>Regex</label>
{{ new_auto_create_rule_form.regex(class="form-control", {{ new_auto_create_rule_form.regex(class="form-control",
placeholder="prefix.*" placeholder="prefix.*") }}
) }}
{{ render_field_errors(new_auto_create_rule_form.regex) }} {{ render_field_errors(new_auto_create_rule_form.regex) }}
<div class="small-text"> <div class="small-text">
For example, if you want aliases that starts with <b>prefix</b> to be automatically created, you can set For example, if you want aliases that starts with <b>prefix</b> to be automatically created, you can set
@ -95,10 +95,7 @@
name="mailbox_ids"> name="mailbox_ids">
{% for mailbox in mailboxes %} {% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" <option value="{{ mailbox.id }}" {% if mailbox.id == current_user.default_mailbox_id %}selected{% endif %}>{{ mailbox.email }}</option>
{% if mailbox.id == current_user.default_mailbox_id %} selected{% endif %}>
{{ mailbox.email }}
</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -128,9 +125,7 @@
{% if auto_create_test_result %} {% if auto_create_test_result %}
<div class="alert {% if auto_create_test_passed %} <div class="alert {% if auto_create_test_passed %}
alert-success {% else %} alert-warning {% endif %}"> alert-success {% else %} alert-warning {% endif %}">{{ auto_create_test_result }}</div>
{{ auto_create_test_result }}
</div>
{% endif %} {% endif %}
</div> </div>
</div> </div>

View file

@ -63,8 +63,8 @@
{% endif %} {% endif %}
<hr /> <hr />
{% endif %} {% endif %}
<div class="{% if not custom_domain.ownership_verified %} disabled-content{% endif %}" <div class="{% if not custom_domain.ownership_verified %}
id="dns-setup"> disabled-content{% endif %}" id="dns-setup">
{% if not custom_domain.ownership_verified %} {% if not custom_domain.ownership_verified %}
<div class="alert alert-warning">A domain ownership must be verified first.</div> <div class="alert alert-warning">A domain ownership must be verified first.</div>
@ -177,9 +177,7 @@
<em data-toggle="tooltip" <em data-toggle="tooltip"
title="Click to copy" title="Click to copy"
class="clipboard" class="clipboard"
data-clipboard-text="{{ spf_record }}"> data-clipboard-text="{{ spf_record }}">{{ spf_record }}</em>
{{ spf_record }}
</em>
</div> </div>
<form method="post" action="#spf-form"> <form method="post" action="#spf-form">
{{ csrf_form.csrf_token }} {{ csrf_form.csrf_token }}
@ -238,9 +236,7 @@
Setting up DKIM is highly recommended to reduce the chance your emails ending up in the recipient's Spam Setting up DKIM is highly recommended to reduce the chance your emails ending up in the recipient's Spam
folder. folder.
</div> </div>
<div class="mb-2"> <div class="mb-2">Add the following CNAME DNS records to your domain.</div>
Add the following CNAME DNS records to your domain.
</div>
{% for dkim_prefix, dkim_cname_value in dkim_records %} {% for dkim_prefix, dkim_cname_value in dkim_records %}
<div class="mb-2 p-3 dns-record"> <div class="mb-2 p-3 dns-record">
@ -256,9 +252,7 @@
title="Click to copy" title="Click to copy"
class="clipboard" class="clipboard"
data-clipboard-text="{{ dkim_cname_value }}." data-clipboard-text="{{ dkim_cname_value }}."
style="overflow-wrap: break-word"> style="overflow-wrap: break-word">{{ dkim_cname_value }}.</em>
{{ dkim_cname_value }}.
</em>
</div> </div>
{% endfor %} {% endfor %}
<div class="alert alert-info"> <div class="alert alert-info">
@ -282,21 +276,15 @@
<input type="hidden" name="form-name" value="check-dkim"> <input type="hidden" name="form-name" value="check-dkim">
{% if custom_domain.dkim_verified %} {% if custom_domain.dkim_verified %}
<button type="submit" class="btn btn-outline-primary"> <button type="submit" class="btn btn-outline-primary">Re-verify</button>
Re-verify
</button>
{% else %} {% else %}
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">Verify</button>
Verify
</button>
{% endif %} {% endif %}
</form> </form>
{% if not dkim_ok %} {% if not dkim_ok %}
<div class="text-danger mt-4"> <div class="text-danger mt-4">
<p> <p>Your DNS is not correctly set.</p>
Your DNS is not correctly set.
</p>
<ul> <ul>
{% for custom_record, retrieved_cname in dkim_errors.items() %} {% for custom_record, retrieved_cname in dkim_errors.items() %}
@ -312,10 +300,8 @@
</div> </div>
{% if custom_domain.dkim_verified %} {% if custom_domain.dkim_verified %}
<div class="text-danger mt-4"> <div class="text-danger mt-4">DKIM is still enabled. Please update your DKIM settings with all CNAME records</div>
DKIM is still enabled. Please update your DKIM settings with all CNAME records {% endif %}
</div>
{% endif %}
{% endif %} {% endif %}
</div> </div>
<hr /> <hr />
@ -330,24 +316,20 @@
{% else %} {% else %}
<span class="cursor" <span class="cursor"
data-toggle="tooltip" data-toggle="tooltip"
data-original-title="DMARC Not Verified">🚫 </span> data-original-title="DMARC Not Verified">🚫</span>
{% endif %} {% endif %}
</div> </div>
<div> <div>
DMARC DMARC
<a href="https://en.wikipedia.org/wiki/DMARC" <a href="https://en.wikipedia.org/wiki/DMARC"
target="_blank" target="_blank"
rel="noopener noreferrer"> rel="noopener noreferrer">(Wikipedia↗)</a>
(Wikipedia↗)
</a>
is designed to protect the domain from unauthorized use, commonly known as email spoofing. is designed to protect the domain from unauthorized use, commonly known as email spoofing.
<br /> <br />
Built around SPF and DKIM, a DMARC policy tells the receiving mail server what to do if Built around SPF and DKIM, a DMARC policy tells the receiving mail server what to do if
neither of those authentication methods passes. neither of those authentication methods passes.
</div> </div>
<div class="mb-2"> <div class="mb-2">Add the following TXT DNS record to your domain.</div>
Add the following TXT DNS record to your domain.
</div>
<div class="mb-2 p-3 dns-record"> <div class="mb-2 p-3 dns-record">
Record: TXT Record: TXT
<br /> <br />
@ -360,9 +342,7 @@
<em data-toggle="tooltip" <em data-toggle="tooltip"
title="Click to copy" title="Click to copy"
class="clipboard" class="clipboard"
data-clipboard-text="{{ dmarc_record }}"> data-clipboard-text="{{ dmarc_record }}">{{ dmarc_record }}</em>
{{ dmarc_record }}
</em>
</div> </div>
<div class="alert alert-info"> <div class="alert alert-info">
Some DNS registrar might require a full record path, in this case please use Some DNS registrar might require a full record path, in this case please use
@ -377,13 +357,9 @@
<input type="hidden" name="form-name" value="check-dmarc"> <input type="hidden" name="form-name" value="check-dmarc">
{% if custom_domain.dmarc_verified %} {% if custom_domain.dmarc_verified %}
<button type="submit" class="btn btn-outline-primary"> <button type="submit" class="btn btn-outline-primary">Re-verify</button>
Re-verify
</button>
{% else %} {% else %}
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">Verify</button>
Verify
</button>
{% endif %} {% endif %}
</form> </form>
{% if not dmarc_ok %} {% if not dmarc_ok %}

View file

@ -34,13 +34,14 @@
. .
</div> </div>
</div> </div>
<div class="{% if not custom_domain.catch_all %} disabled-content{% endif %}"> <div class="{% if not custom_domain.catch_all %}
disabled-content{% endif %}">
<div> <div>
Auto-created aliases are automatically owned by the following mailboxes Auto-created aliases are automatically owned by the following mailboxes
<i class="fe fe-corner-right-down"></i> <i class="fe fe-corner-right-down"></i>
. .
</div> </div>
{% set domain_mailboxes=custom_domain.mailboxes %} {% set domain_mailboxes = custom_domain.mailboxes %}
<form method="post" class="mt-2"> <form method="post" class="mt-2">
{{ csrf_form.csrf_token }} {{ csrf_form.csrf_token }}
<input type="hidden" name="form-name" value="update"> <input type="hidden" name="form-name" value="update">
@ -54,10 +55,7 @@
name="mailbox_ids"> name="mailbox_ids">
{% for mailbox in mailboxes %} {% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" <option value="{{ mailbox.id }}" {% if mailbox in domain_mailboxes %}selected{% endif %}>{{ mailbox.email }}</option>
{% if mailbox in domain_mailboxes %} selected{% endif %}>
{{ mailbox.email }}
</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>

View file

@ -45,7 +45,7 @@
<td>Link a New Key</td> <td>Link a New Key</td>
<td></td> <td></td>
<td class="text-center"> <td class="text-center">
<a href="{{ url_for('dashboard.fido_setup') }}"> <a href="{{ url_for("dashboard.fido_setup") }}">
<button class="btn btn-outline-success">Link</button> <button class="btn btn-outline-success">Link</button>
</a> </a>
</td> </td>

View file

@ -61,8 +61,7 @@
class="btn btn-success dropdown-toggle btn-group-border-left" class="btn btn-success dropdown-toggle btn-group-border-left"
data-toggle="dropdown" data-toggle="dropdown"
aria-haspopup="true" aria-haspopup="true"
aria-expanded="false"> aria-expanded="false"></button>
</button>
<div class="dropdown-menu dropdown-menu-right border-left" <div class="dropdown-menu dropdown-menu-right border-left"
aria-labelledby="btnGroupDrop1"> aria-labelledby="btnGroupDrop1">
<div> <div>
@ -125,7 +124,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Aliases</div> <div class="subheader">Aliases</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">All time</div> style="order: 2;
margin-left: auto;
font-size: .8rem">All time</div>
</div> </div>
<div class="h1 m-0">{{ stats.nb_alias }}</div> <div class="h1 m-0">{{ stats.nb_alias }}</div>
</div> </div>
@ -137,7 +138,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Forwarded</div> <div class="subheader">Forwarded</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">Last 14 days</div> style="order: 2;
margin-left: auto;
font-size: .8rem">Last 14 days</div>
</div> </div>
<div class="h1 m-0">{{ stats.nb_forward }}</div> <div class="h1 m-0">{{ stats.nb_forward }}</div>
</div> </div>
@ -149,7 +152,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Replies/Sent</div> <div class="subheader">Replies/Sent</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">Last 14 days</div> style="order: 2;
margin-left: auto;
font-size: .8rem">Last 14 days</div>
</div> </div>
<div class="h1 m-0">{{ stats.nb_reply }}</div> <div class="h1 m-0">{{ stats.nb_reply }}</div>
</div> </div>
@ -161,7 +166,9 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="subheader">Blocked</div> <div class="subheader">Blocked</div>
<div class="text-muted" <div class="text-muted"
style="order: 2; margin-left: auto; font-size: .8rem">Last 14 days</div> style="order: 2;
margin-left: auto;
font-size: .8rem">Last 14 days</div>
</div> </div>
<div class="h1 m-0">{{ stats.nb_block }}</div> <div class="h1 m-0">{{ stats.nb_block }}</div>
</div> </div>
@ -177,52 +184,28 @@
<select name="sort" <select name="sort"
onchange="this.form.submit()" onchange="this.form.submit()"
class="form-control mr-3 shadow"> class="form-control mr-3 shadow">
<option value="" {% if sort == "" %} selected{% endif %}> <option value="" {% if sort == "" %}selected{% endif %}>Sort by most recent activity</option>
Sort by most recent activity <option value="old2new" {% if sort == "old2new" %}selected{% endif %}>Alias Old-Recent</option>
</option> <option value="new2old" {% if sort == "new2old" %}selected{% endif %}>Alias Recent-Old</option>
<option value="old2new" {% if sort == "old2new" %} selected{% endif %}> <option value="a2z" {% if sort == "a2z" %}selected{% endif %}>Alias A-Z</option>
Alias Old-Recent <option value="z2a" {% if sort == "z2a" %}selected{% endif %}>Alias Z-A</option>
</option>
<option value="new2old" {% if sort == "new2old" %} selected{% endif %}>
Alias Recent-Old
</option>
<option value="a2z" {% if sort == "a2z" %} selected{% endif %}>
Alias A-Z
</option>
<option value="z2a" {% if sort == "z2a" %} selected{% endif %}>
Alias Z-A
</option>
</select> </select>
<select name="filter" <select name="filter"
onchange="this.form.submit()" onchange="this.form.submit()"
class="form-control mr-3 shadow" class="form-control mr-3 shadow"
style="max-width: 200px"> style="max-width: 200px">
<option value="" {% if filter == "" %} selected{% endif %}> <option value="" {% if filter == "" %}selected{% endif %}>All Aliases</option>
All Aliases <option value="pinned" {% if filter == "pinned" %}selected{% endif %}>Pinned Aliases</option>
</option> <option value="enabled" {% if filter == "enabled" %}selected{% endif %}>Only Enabled Aliases</option>
<option value="pinned" {% if filter == "pinned" %} selected{% endif %}> <option value="disabled" {% if filter == "disabled" %}selected{% endif %}>Only Disabled Aliases</option>
Pinned Aliases <option value="hibp" {% if filter == "hibp" %}selected{% endif %}>Only Aliases Found In Data Breaches</option>
</option>
<option value="enabled" {% if filter == "enabled" %} selected{% endif %}>
Only Enabled Aliases
</option>
<option value="disabled" {% if filter == "disabled" %} selected{% endif %}>
Only Disabled Aliases
</option>
<option value="hibp" {% if filter == "hibp" %} selected{% endif %}>
Only Aliases Found In Data Breaches
</option>
{% for mailbox in current_user.mailboxes() %} {% for mailbox in current_user.mailboxes() %}
<option value="mailbox:{{ mailbox.id }}" {% if filter == "mailbox:" ~ mailbox.id %} <option value="mailbox:{{ mailbox.id }}" {% if filter == "mailbox:" ~ mailbox.id %}selected{% endif %}>{{ mailbox.email }}'s aliases</option>
selected {% endif %}>
{{ mailbox.email }}'s aliases
</option>
{% endfor %} {% endfor %}
{% for directory in current_user.directories %} {% for directory in current_user.directories %}
<option value="directory:{{ directory.id }}" {% if filter == "directory:" ~ directory.id %} <option value="directory:{{ directory.id }}" {% if filter == "directory:" ~ directory.id %}selected{% endif %}>
selected {% endif %}>
Directory <b>{{ directory.name }}</b> aliases Directory <b>{{ directory.name }}</b> aliases
</option> </option>
{% endfor %} {% endfor %}
@ -237,7 +220,7 @@
<div style="margin-left: auto"> <div style="margin-left: auto">
{% if query or sort or filter %} {% if query or sort or filter %}
<a href="{{ url_for('dashboard.index') }}" <a href="{{ url_for("dashboard.index") }}"
class="btn btn-outline-secondary">Reset</a> class="btn btn-outline-secondary">Reset</a>
{% endif %} {% endif %}
</div> </div>
@ -251,10 +234,11 @@
{% set alias = alias_info.alias %} {% set alias = alias_info.alias %}
<div class="col-12 col-lg-6" id="alias-container-{{ alias.id }}"> <div class="col-12 col-lg-6" id="alias-container-{{ alias.id }}">
<div class="card p-4 shadow-sm {% if alias.id == highlight_alias_id %} highlight-row{% endif %} "> <div class="card p-4 shadow-sm {% if alias.id == highlight_alias_id %}highlight-row{% endif %} ">
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<span class="{% if alias.id == highlight_alias_id %} highlighted{% endif %} clipboard cursor mb-0" {% if loop.index ==1 %} <span class="{% if alias.id == highlight_alias_id %}
highlighted{% endif %} clipboard cursor mb-0" {% if loop.index ==1 %}
data-intro="This is your first <em>alias</em>. data-intro="This is your first <em>alias</em>.
<br /> <br />
<br /> <br />
@ -358,7 +342,15 @@
</div> </div>
<div class="d-flex mb-2"> <div class="d-flex mb-2">
<div class="flex-grow-1 mr-2"> <div class="flex-grow-1 mr-2">
<textarea id="note-{{ alias.id }}" name="note" class="form-control" style="font-size: 12px" rows="2" placeholder="e.g. where the alias is used or why is it created" onchange="handleNoteChange({{ alias.id }}, '{{ alias.email }}')" onfocus="handleNoteFocus({{ alias.id }})" onblur="handleNoteBlur({{ alias.id }})">{{ alias.note or "" }}</textarea> <textarea id="note-{{ alias.id }}"
name="note"
class="form-control"
style="font-size: 12px"
rows="2"
placeholder="e.g. where the alias is used or why is it created"
onchange="handleNoteChange({{ alias.id }}, '{{ alias.email }}')"
onfocus="handleNoteFocus({{ alias.id }})"
onblur="handleNoteBlur({{ alias.id }})">{{ alias.note or "" }}</textarea>
</div> </div>
</div> </div>
<!-- Send Email && More button --> <!-- Send Email && More button -->
@ -399,27 +391,21 @@
</div> </div>
<!-- END Send Email && More button --> <!-- END Send Email && More button -->
<!-- Collapse section --> <!-- Collapse section -->
<div class="{% if not current_user.expand_alias_info %} collapse{% endif %} mt-2" <div class="{% if not current_user.expand_alias_info %}
id="alias-{{ alias.id }}"> collapse{% endif %} mt-2" id="alias-{{ alias.id }}">
{% if alias_info.latest_email_log != None %} {% if alias_info.latest_email_log != None %}
<div style="font-size: 12px"> <div style="font-size: 12px">Alias created {{ alias.created_at | dt }}</div>
Alias created {{ alias.created_at | dt }}
</div>
{% endif %} {% endif %}
<span class="alias-activity">{{ alias_info.nb_forward }}</span> forwarded, <span class="alias-activity">{{ alias_info.nb_forward }}</span> forwarded,
<span class="alias-activity">{{ alias_info.nb_blocked }}</span> blocked, <span class="alias-activity">{{ alias_info.nb_blocked }}</span> blocked,
<span class="alias-activity">{{ alias_info.nb_reply }}</span> sent <span class="alias-activity">{{ alias_info.nb_reply }}</span> sent
in the last 14 days in the last 14 days
<a href="{{ url_for('dashboard.alias_log', alias_id=alias.id) }}" <a href="{{ url_for('dashboard.alias_log', alias_id=alias.id) }}"
class="btn btn-sm btn-link"> class="btn btn-sm btn-link">See All &nbsp;</a>
See All &nbsp;
</a>
{% if mailboxes|length > 1 %} {% if mailboxes|length > 1 %}
<div class="small-text"> <div class="small-text">Current mailbox</div>
Current mailbox
</div>
<div class="d-flex"> <div class="d-flex">
<div class="flex-grow-1 mr-2"> <div class="flex-grow-1 mr-2">
<select required <select required
@ -431,10 +417,7 @@
onchange="handleMailboxChange({{ alias.id }}, '{{ alias.email }}')"> onchange="handleMailboxChange({{ alias.id }}, '{{ alias.email }}')">
{% for mailbox in mailboxes %} {% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" {% if alias_info.contain_mailbox(mailbox.id) %} <option value="{{ mailbox.id }}" {% if alias_info.contain_mailbox(mailbox.id) %}selected{% endif %}>{{ mailbox.email }}</option>
selected {% endif %}>
{{ mailbox.email }}
</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -502,11 +485,7 @@
<input type="hidden" name="form-name" value="delete-alias"> <input type="hidden" name="form-name" value="delete-alias">
<input type="hidden" name="alias-id" value="{{ alias.id }}"> <input type="hidden" name="alias-id" value="{{ alias.id }}">
<input type="hidden" name="alias" class="alias" value="{{ alias.email }}"> <input type="hidden" name="alias" class="alias" value="{{ alias.email }}">
<span class="btn btn-link btn-sm float-right text-danger" <span class="btn btn-link btn-sm float-right text-danger" onclick="confirmDeleteAlias.call(this)" {% if alias.custom_domain %}data-custom-domain-trash-url="{{ alias.custom_domain.get_trash_url() }}"{% endif %} data-alias="{{ alias.id }}" data-alias-email="{{ alias.email }}">
onclick="confirmDeleteAlias.call(this)"
{% if alias.custom_domain %} data-custom-domain-trash-url="{{ alias.custom_domain.get_trash_url() }}"{% endif %}
data-alias="{{ alias.id }}"
data-alias-email="{{ alias.email }}">
Delete&nbsp; &nbsp;<i class="dropdown-icon fe fe-trash-2 text-danger"></i> Delete&nbsp; &nbsp;<i class="dropdown-icon fe fe-trash-2 text-danger"></i>
</span> </span>
</form> </form>
@ -527,14 +506,12 @@
<nav aria-label="Alias navigation"> <nav aria-label="Alias navigation">
<ul class="pagination"> <ul class="pagination">
<li class="page-item mr-1"> <li class="page-item mr-1">
<a class="btn btn-outline-primary {% if page == 0 %}disabled{% endif %}" <a class="btn btn-outline-primary {% if page == 0 %}disabled{% endif %}" href="{{ url_for('dashboard.index', page=page-1, query=query, sort=sort, filter=filter) }}">
href="{{ url_for('dashboard.index', page=page-1, query=query, sort=sort, filter=filter) }}">
Previous Previous
</a> </a>
</li> </li>
<li class="page-item"> <li class="page-item">
<a class="btn btn-outline-primary {% if last_page %}disabled{% endif %}" <a class="btn btn-outline-primary {% if last_page %}disabled{% endif %}" href="{{ url_for('dashboard.index', page=page+1, query=query, sort=sort, filter=filter) }}">
href="{{ url_for('dashboard.index', page=page+1, query=query, sort=sort, filter=filter) }}">
Next Next
</a> </a>
</li> </li>

View file

@ -22,21 +22,19 @@
<div class="alert alert-danger" role="alert">This feature is only available in premium plan.</div> <div class="alert alert-danger" role="alert">This feature is only available in premium plan.</div>
{% endif %} {% endif %}
<div class="alert alert-primary collapse {% if mailboxes|length == 1 %} show{% endif %}" <div class="alert alert-primary collapse {% if mailboxes|length == 1 %}show{% endif %}" id="howtouse" role="alert">
id="howtouse"
role="alert">
A <em>mailbox</em> is just another personal email address. When creating a new alias, you could choose A <em>mailbox</em> is just another personal email address. When creating a new alias, you could choose
the the
mailbox that <em>owns</em> this alias, i.e: mailbox that <em>owns</em> this alias, i.e:
<br/> <br />
- all emails sent to this alias will be forwarded to this mailbox - all emails sent to this alias will be forwarded to this mailbox
<br/> <br />
- from this mailbox, you can reply/send emails from the alias. - from this mailbox, you can reply/send emails from the alias.
<br/> <br />
<br/> <br />
When you signed up, a mailbox is automatically created with your email <b>{{ current_user.email }}</b> When you signed up, a mailbox is automatically created with your email <b>{{ current_user.email }}</b>
<br/> <br />
<br/> <br />
The mailbox doesn't have to be your email: it can be your friend's email The mailbox doesn't have to be your email: it can be your friend's email
if you want to create aliases for your buddy. if you want to create aliases for your buddy.
</div> </div>
@ -75,9 +73,9 @@
</h5> </h5>
<h6 class="card-subtitle mb-2 text-muted"> <h6 class="card-subtitle mb-2 text-muted">
Created {{ mailbox.created_at | dt }} Created {{ mailbox.created_at | dt }}
<br/> <br />
<span class="font-weight-bold">{{ mailbox.nb_alias() }}</span> aliases. <span class="font-weight-bold">{{ mailbox.nb_alias() }}</span> aliases.
<br/> <br />
</h6> </h6>
<a href="{{ url_for('dashboard.mailbox_detail_route', mailbox_id=mailbox.id) }}">Edit <a href="{{ url_for('dashboard.mailbox_detail_route', mailbox_id=mailbox.id) }}">Edit
</a> </a>
@ -92,9 +90,7 @@
<input type="hidden" name="form-name" value="set-default"> <input type="hidden" name="form-name" value="set-default">
<input type="hidden" class="mailbox" value="{{ mailbox.email }}"> <input type="hidden" class="mailbox" value="{{ mailbox.email }}">
<input type="hidden" name="mailbox_id" value="{{ mailbox.id }}"> <input type="hidden" name="mailbox_id" value="{{ mailbox.id }}">
<button class="card-link btn btn-link {% if mailbox.id == current_user.default_mailbox_id %} disabled{% endif %}"> <button class="card-link btn btn-link {% if mailbox.id == current_user.default_mailbox_id %}disabled{% endif %}">Set As Default Mailbox</button>
Set As Default Mailbox
</button>
</form> </form>
</div> </div>
{% endif %} {% endif %}
@ -105,22 +101,16 @@
<input type="hidden" class="mailbox" value="{{ mailbox.email }}"> <input type="hidden" class="mailbox" value="{{ mailbox.email }}">
<input type="hidden" name="mailbox_id" value="{{ mailbox.id }}"> <input type="hidden" name="mailbox_id" value="{{ mailbox.id }}">
<select hidden name="transfer_mailbox_id" value=""> <select hidden name="transfer_mailbox_id" value="">
<option value="-1"> <option value="-1">Delete my aliases</option>
Delete my aliases
</option>
{% for mailbox_opt in mailboxes %} {% for mailbox_opt in mailboxes %}
{% if mailbox_opt.verified and mailbox_opt.id != mailbox.id %} {% if mailbox_opt.verified and mailbox_opt.id != mailbox.id %}
<option value="{{ mailbox_opt.id }}"> <option value="{{ mailbox_opt.id }}">{{ mailbox_opt.email }}</option>
{{ mailbox_opt.email }}
</option>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</select> </select>
<span class="card-link btn btn-link text-danger float-right delete-mailbox {% if mailbox.id == current_user.default_mailbox_id %} disabled{% endif %}"> <span class="card-link btn btn-link text-danger float-right delete-mailbox {% if mailbox.id == current_user.default_mailbox_id %}disabled{% endif %}">Delete</span>
Delete
</span>
</form> </form>
</div> </div>
</div> </div>

View file

@ -60,9 +60,7 @@
<div class="mt-2"> <div class="mt-2">
<span class="text-danger">Pending change: {{ pending_email }}</span> <span class="text-danger">Pending change: {{ pending_email }}</span>
<a href="{{ url_for('dashboard.cancel_mailbox_change_route', mailbox_id=mailbox.id) }}" <a href="{{ url_for('dashboard.cancel_mailbox_change_route', mailbox_id=mailbox.id) }}"
class="btn btn-secondary btn-sm"> class="btn btn-secondary btn-sm">Cancel mailbox change</a>
Cancel mailbox change
</a>
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -123,13 +121,15 @@
{{ csrf_form.csrf_token }} {{ csrf_form.csrf_token }}
<div class="form-group"> <div class="form-group">
<label class="form-label">PGP Public Key</label> <label class="form-label">PGP Public Key</label>
<textarea name="pgp" {% if not current_user.is_premium() %} disabled {% endif %} class="form-control" rows=10 id="pgp-public-key" placeholder="(Drag and drop or paste your pgp public key here)&#10;-----BEGIN PGP PUBLIC KEY BLOCK-----">{{ mailbox.pgp_public_key or "" }}</textarea> <textarea name="pgp"
{% if not current_user.is_premium() %}disabled{% endif %}
class="form-control"
rows="10"
id="pgp-public-key"
placeholder="(Drag and drop or paste your pgp public key here)&#10;-----BEGIN PGP PUBLIC KEY BLOCK-----">{{ mailbox.pgp_public_key or "" }}</textarea>
</div> </div>
<input type="hidden" name="form-name" value="pgp"> <input type="hidden" name="form-name" value="pgp">
<button class="btn btn-primary" name="action" {% if not current_user.is_premium() %} <button class="btn btn-primary" name="action" {% if not current_user.is_premium() %}disabled{% endif %} value="save">Save</button>
disabled {% endif %} value="save">
Save
</button>
{% if mailbox.pgp_finger_print %} {% if mailbox.pgp_finger_print %}
<button class="btn btn-danger float-right" name="action" value="remove">Remove</button> <button class="btn btn-danger float-right" name="action" value="remove">Remove</button>

View file

@ -8,7 +8,7 @@
Mailbox <b>{{ mailbox.email }}</b> verified, you can now start creating alias with it Mailbox <b>{{ mailbox.email }}</b> verified, you can now start creating alias with it
</div> </div>
<div class="mx-auto"> <div class="mx-auto">
<a href="{{ url_for('dashboard.index') }}" class="btn btn-primary">Go To Home Page</a> <a href="{{ url_for("dashboard.index") }}" class="btn btn-primary">Go To Home Page</a>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -17,13 +17,9 @@
white-space: normal; white-space: normal;
overflow: hidden; overflow: hidden;
max-height: 100px; max-height: 100px;
text-overflow: ellipsis;"> text-overflow: ellipsis">{{ notification.message | safe }}</div>
{{ notification.message | safe }}
</div>
<a href="{{ url_for('dashboard.notification_route', notification_id=notification.id) }}" <a href="{{ url_for('dashboard.notification_route', notification_id=notification.id) }}"
class="mt-2 btn btn-outline-primary"> class="mt-2 btn btn-outline-primary">More ➡</a>
More ➡
</a>
<div class="small text-muted mt-2">{{ notification.created_at | dt }}</div> <div class="small text-muted mt-2">{{ notification.created_at | dt }}</div>
</div> </div>
</div> </div>
@ -36,16 +32,12 @@
<nav aria-label="Notification navigation"> <nav aria-label="Notification navigation">
<ul class="pagination"> <ul class="pagination">
<li class="page-item mr-1"> <li class="page-item mr-1">
<a class="btn btn-outline-primary {% if page == 0 %}disabled{% endif %}" <a class="btn btn-outline-primary {% if page == 0 %}disabled{% endif %}" href="{{ url_for('dashboard.notifications_route', page=page-1) }}">
href="{{ url_for('dashboard.notifications_route', page=page-1) }}">
Previous Previous
</a> </a>
</li> </li>
<li class="page-item"> <li class="page-item">
<a class="btn btn-outline-primary {% if last_page %}disabled{% endif %}" <a class="btn btn-outline-primary {% if last_page %}disabled{% endif %}" href="{{ url_for('dashboard.notifications_route', page=page+1) }}">Next</a>
href="{{ url_for('dashboard.notifications_route', page=page+1) }}">
Next
</a>
</li> </li>
</ul> </ul>
</nav> </nav>

View file

@ -9,7 +9,7 @@
if (window.Paddle === undefined) { if (window.Paddle === undefined) {
console.log("cannot load Paddle from CDN"); console.log("cannot load Paddle from CDN");
// split string to avoid djlint incorrectly formatting the file // split string to avoid djlint incorrectly formatting the file
document.write('<' + 'script src="/static/vendor/paddle.js"><\/script' + '>'); document.write('<' + 'script src="/static/vendor/paddle.js"><\/script ' + '>');
} }
</script> </script>
<style type="text/css"> <style type="text/css">
@ -144,9 +144,7 @@
{% set sub = current_user.get_paddle_subscription() %} {% set sub = current_user.get_paddle_subscription() %}
<button class="{{ 'invisible' if sub or manual_sub or coinbase_sub }} btn btn-lg btn-outline-secondary w-100 btn-no-pointer" <button class="{{ 'invisible' if sub or manual_sub or coinbase_sub }} btn btn-lg btn-outline-secondary w-100 btn-no-pointer"
aria-disabled="true" aria-disabled="true"
disabled> disabled>Current plan</button>
Current plan
</button>
</div> </div>
</div> </div>
<ul class="list-unstyled"> <ul class="list-unstyled">
@ -172,9 +170,7 @@
<div class="h3 my-3">$4 / month</div> <div class="h3 my-3">$4 / month</div>
<div class="text-center mt-4 mb-6"> <div class="text-center mt-4 mb-6">
<button class="btn btn-primary btn-lg w-100" <button class="btn btn-primary btn-lg w-100"
onclick="upgradePaddle({{ PADDLE_MONTHLY_PRODUCT_ID }})"> onclick="upgradePaddle({{ PADDLE_MONTHLY_PRODUCT_ID }})">Upgrade to Premium</button>
Upgrade to Premium
</button>
</div> </div>
</div> </div>
<ul class="list-unstyled"> <ul class="list-unstyled">
@ -287,9 +283,7 @@
{% set sub = current_user.get_paddle_subscription() %} {% set sub = current_user.get_paddle_subscription() %}
<button class="{{ 'invisible' if sub or manual_sub or coinbase_sub }} btn btn-lg btn-outline-secondary w-100 btn-no-pointer" <button class="{{ 'invisible' if sub or manual_sub or coinbase_sub }} btn btn-lg btn-outline-secondary w-100 btn-no-pointer"
aria-disabled="true" aria-disabled="true"
disabled> disabled>Current plan</button>
Current plan
</button>
</div> </div>
</div> </div>
<ul class="list-unstyled"> <ul class="list-unstyled">
@ -315,9 +309,7 @@
<div class="h3 my-3">$30 / year</div> <div class="h3 my-3">$30 / year</div>
<div class="text-center mt-4 mb-6"> <div class="text-center mt-4 mb-6">
<button class="btn btn-primary btn-lg w-100" <button class="btn btn-primary btn-lg w-100"
onclick="upgradePaddle({{ PADDLE_YEARLY_PRODUCT_ID }})"> onclick="upgradePaddle({{ PADDLE_YEARLY_PRODUCT_ID }})">Upgrade to Premium</button>
Upgrade to Premium
</button>
</div> </div>
</div> </div>
<ul class="list-unstyled"> <ul class="list-unstyled">
@ -447,18 +439,10 @@
We use <a href="https://paddle.com" target="_blank" rel="noopener noreferrer">Paddle <i class="fe fe-external-link"></i></a> by default for handling payments via credit cards and PayPal. Paddle currently supports the following payment methods: We use <a href="https://paddle.com" target="_blank" rel="noopener noreferrer">Paddle <i class="fe fe-external-link"></i></a> by default for handling payments via credit cards and PayPal. Paddle currently supports the following payment methods:
</p> </p>
<ul> <ul>
<li> <li>Cards (including Mastercard, Visa, Maestro, American Express, Discover, Diners Club, JCB, UnionPay, and Mada)</li>
Cards (including Mastercard, Visa, Maestro, American Express, Discover, Diners Club, JCB, UnionPay, and Mada) <li>PayPal</li>
</li> <li>Apple Pay</li>
<li> <li>Wire Transfers (ACH/SEPA/BACS)</li>
PayPal
</li>
<li>
Apple Pay
</li>
<li>
Wire Transfers (ACH/SEPA/BACS)
</li>
</ul> </ul>
<p> <p>
More information can be found on More information can be found on
@ -482,7 +466,7 @@
</p> </p>
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<a class="btn btn-outline-primary text-center" <a class="btn btn-outline-primary text-center"
href="{{ url_for('dashboard.coinbase_checkout_route') }}" href="{{ url_for("dashboard.coinbase_checkout_route") }}"
target="_blank" target="_blank"
rel="noopener noreferrer"> rel="noopener noreferrer">
Upgrade to Premium - cryptocurrency Upgrade to Premium - cryptocurrency
@ -520,7 +504,7 @@
<div class="card-body"> <div class="card-body">
<p> <p>
To redeem or buy a coupon, please go to the To redeem or buy a coupon, please go to the
<a href="{{ url_for('dashboard.coupon_route') }}">coupon page</a>. The coupon code can be used by you or given to someone as a gift. <a href="{{ url_for("dashboard.coupon_route") }}">coupon page</a>. The coupon code can be used by you or given to someone as a gift.
</p> </p>
</div> </div>
</div> </div>
@ -554,18 +538,12 @@
sending emails. Concretely: sending emails. Concretely:
</p> </p>
<ul> <ul>
<li> <li>All aliases/domains/directories/mailboxes you have created are kept and continue working normally.</li>
All aliases/domains/directories/mailboxes you have created are kept and continue working normally. <li>You cannot create new aliases if you exceed the free plan limit, i.e. have more than 10 aliases.</li>
</li>
<li>
You cannot create new aliases if you exceed the free plan limit, i.e. have more than 10 aliases.
</li>
<li> <li>
As features like catch-all or directory allow you to create aliases on-the-fly, those aliases cannot be automatically created if you have more than 10 aliases. As features like catch-all or directory allow you to create aliases on-the-fly, those aliases cannot be automatically created if you have more than 10 aliases.
</li> </li>
<li> <li>You cannot add new domain, directory or mailbox.</li>
You cannot add new domain, directory or mailbox.
</li>
</ul> </ul>
<p> <p>
For example, if you have 100 aliases by the time your subscription ends, these 100 aliases will continue receiving and sending emails normally. You cannot however create new aliases. For example, if you have 100 aliases by the time your subscription ends, these 100 aliases will continue receiving and sending emails normally. You cannot however create new aliases.
@ -630,19 +608,11 @@
aria-labelledby="pricing-faq-question-discounts" aria-labelledby="pricing-faq-question-discounts"
data-parent="#pricing-faq"> data-parent="#pricing-faq">
<div class="card-body"> <div class="card-body">
<p> <p>We offer important discounts or free premium for:</p>
We offer important discounts or free premium for:
</p>
<ul> <ul>
<li> <li>students, professors or technical staffs working at an educational institute</li>
students, professors or technical staffs working at an educational institute <li>activists, dissidents or journalists</li>
</li> <li>charity organizations</li>
<li>
activists, dissidents or journalists
</li>
<li>
charity organizations
</li>
</ul> </ul>
<p> <p>
Please send us an email at <a href="mailto:support@simplelogin.zendesk.com" target="_blank">support@simplelogin.zendesk.com</a> for more info. Please send us an email at <a href="mailto:support@simplelogin.zendesk.com" target="_blank">support@simplelogin.zendesk.com</a> for more info.
@ -677,9 +647,7 @@
aria-labelledby="pricing-faq-question-refund" aria-labelledby="pricing-faq-question-refund"
data-parent="#pricing-faq"> data-parent="#pricing-faq">
<div class="card-body"> <div class="card-body">
<p> <p>No we don't have a refund policy because SimpleLogin has a trial period where you can try all premium features.</p>
No we don't have a refund policy because SimpleLogin has a trial period where you can try all premium features.
</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -34,7 +34,7 @@
{% endif %} {% endif %}
{% for referral in referrals %} {% for referral in referrals %}
<div class="card p-4 shadow-sm {% if referral.id == highlight_id %} highlight-row{% endif %}"> <div class="card p-4 shadow-sm {% if referral.id == highlight_id %}highlight-row{% endif %}">
<form method="post"> <form method="post">
<input type="hidden" name="form-name" value="update"> <input type="hidden" name="form-name" value="update">
<input type="hidden" name="referral-id" value="{{ referral.id }}"> <input type="hidden" name="referral-id" value="{{ referral.id }}">
@ -102,9 +102,7 @@
title="Click to copy" title="Click to copy"
class="clipboard" class="clipboard"
data-clipboard-text="{{ '?slref=' + referral.code }}" data-clipboard-text="{{ '?slref=' + referral.code }}"
style="overflow-wrap: break-word"> style="overflow-wrap: break-word">?slref={{ referral.code }}</em>
?slref={{ referral.code }}
</em>
to any link on SimpleLogin website. to any link on SimpleLogin website.
</div> </div>
<div> <div>

View file

@ -48,7 +48,7 @@
{% set refused_email = email_log.refused_email %} {% set refused_email = email_log.refused_email %}
{% set contact = email_log.contact %} {% set contact = email_log.contact %}
{% set alias = contact.alias %} {% set alias = contact.alias %}
<div class="card p-4 shadow-sm {% if email_log.id == highlight_id %} highlight-row{% endif %}"> <div class="card p-4 shadow-sm {% if email_log.id == highlight_id %}highlight-row{% endif %}">
<div class="small-text"> <div class="small-text">
Sent {{ refused_email.created_at | dt }} Sent {{ refused_email.created_at | dt }}
{% if email_log.bounced %} {% if email_log.bounced %}
@ -70,9 +70,7 @@
To: {{ alias.email }} To: {{ alias.email }}
<a href='{{ url_for("dashboard.index", highlight_alias_id=alias.id) }}' <a href='{{ url_for("dashboard.index", highlight_alias_id=alias.id) }}'
class="text-danger small-text" class="text-danger small-text"
style="text-decoration: underline"> style="text-decoration: underline">Disable Alias</a>
Disable Alias
</a>
</span> </span>
{% endif %} {% endif %}
{% if refused_email.deleted %} {% if refused_email.deleted %}

File diff suppressed because it is too large Load diff

View file

@ -23,16 +23,14 @@
<div class="alert alert-danger" role="alert"> <div class="alert alert-danger" role="alert">
This feature is only available on Premium plan. This feature is only available on Premium plan.
<a href="{{ url_for('dashboard.pricing') }}" <a href="{{ url_for("dashboard.pricing") }}"
target="_blank" target="_blank"
rel="noopener noreferrer"> rel="noopener noreferrer">
Upgrade<i class="fe fe-external-link"></i> Upgrade<i class="fe fe-external-link"></i>
</a> </a>
</div> </div>
{% endif %} {% endif %}
<div class="alert alert-primary collapse {% if not subdomains %} show{% endif %}" <div class="alert alert-primary collapse {% if not subdomains %}show{% endif %}" id="howtouse" role="alert">
id="howtouse"
role="alert">
You can use subdomain to quickly create email aliases without opening SimpleLogin app. You can use subdomain to quickly create email aliases without opening SimpleLogin app.
<br /> <br />
Handy when you need to quickly give out an email address, for example on a phone call, in a meeting or just Handy when you need to quickly give out an email address, for example on a phone call, in a meeting or just
@ -65,8 +63,7 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
<div class="row {% if current_user.subdomain_quota <= 0 %} disabled-content{% endif %}" <div class="row {% if current_user.subdomain_quota <= 0 %}disabled-content{% endif %}" id="new-subdomain">
id="new-subdomain">
<div class="col"> <div class="col">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
@ -88,12 +85,7 @@
<div class="form-group"> <div class="form-group">
<label>Root domain</label> <label>Root domain</label>
<select name="domain" v-model="domain" class="form-control"> <select name="domain" v-model="domain" class="form-control">
{% for sl_domain in sl_domains %} {% for sl_domain in sl_domains %}<option value="{{ sl_domain.domain }}">{{ sl_domain.domain }}</option>{% endfor %}
<option value="{{ sl_domain.domain }}">
{{ sl_domain.domain }}
</option>
{% endfor %}
</select> </select>
</div> </div>
<button class="btn btn-primary">Create</button> <button class="btn btn-primary">Create</button>

View file

@ -1,6 +1,6 @@
{% extends "default.html" %} {% extends "default.html" %}
{% set active_page = 'dashboard' %} {% set active_page = "dashboard" %}
{% block title %}Support{% endblock %} {% block title %}Support{% endblock %}
{% block default_content %} {% block default_content %}
@ -10,7 +10,7 @@
<div class="card-title mb-3">Report a problem</div> <div class="card-title mb-3">Report a problem</div>
<div class="alert alert-info"> <div class="alert alert-info">
If an email cannot be delivered to your mailbox, please check If an email cannot be delivered to your mailbox, please check
<a href="{{ url_for('dashboard.notifications_route') }}"> <a href="{{ url_for("dashboard.notifications_route") }}">
your your
notifications notifications
</a> </a>
@ -28,7 +28,12 @@
<form id="supportZendeskForm" method="post" enctype="multipart/form-data"> <form id="supportZendeskForm" method="post" enctype="multipart/form-data">
<div class="mt-4 mb-5"> <div class="mt-4 mb-5">
<label for="issueDescription" class="form-label font-weight-bold">What happened?</label> <label for="issueDescription" class="form-label font-weight-bold">What happened?</label>
<textarea class="form-control" required name="ticket_content" id="issueDescription" rows="3" placeholder="Please provide as much information as possible. For example which alias(es), mailbox(es) are affected, if this is a persistent issue...">{{- ticket_content or '' -}}</textarea> <textarea class="form-control"
required
name="ticket_content"
id="issueDescription"
rows="3"
placeholder="Please provide as much information as possible. For example which alias(es), mailbox(es) are affected, if this is a persistent issue...">{{- ticket_content or '' -}}</textarea>
</div> </div>
<div class="mt-5 font-weight-bold">Attach files to support request</div> <div class="mt-5 font-weight-bold">Attach files to support request</div>
<div class="text-muted">Only images, text and emails are accepted</div> <div class="text-muted">Only images, text and emails are accepted</div>
@ -57,9 +62,7 @@
<button class="btn btn-outline-primary" <button class="btn btn-outline-primary"
type="button" type="button"
@click="generateRandomAlias" @click="generateRandomAlias"
id="button-addon2"> id="button-addon2">Generate a random alias</button>
Generate a random alias
</button>
</div> </div>
</div> </div>
<div class="mt-5"> <div class="mt-5">

View file

@ -64,9 +64,9 @@
{# <div class="form-group">#} {# <div class="form-group">#}
{# <label class="form-label">Tell us about your app</label>#} {# <label class="form-label">Tell us about your app</label>#}
{# {{ approval_form.description(#} {# {{ approval_form.description(#}
{# class="form-control", rows="10",#} {# class="form-control", rows="10",#}
{# placeholder="This information is used for approving your application. Please give us as much info as you can, for example where you plan to use SimpleLogin, for which community, etc."#} {# placeholder="This information is used for approving your application. Please give us as much info as you can, for example where you plan to use SimpleLogin, for which community, etc."#}
{# ) }}#} {#) }}#}
{# {{ render_field_errors(approval_form.description) }}#} {# {{ render_field_errors(approval_form.description) }}#}
{# </div>#} {# </div>#}
{##} {##}

View file

@ -7,14 +7,9 @@
<div class="form-group"> <div class="form-group">
<label class="form-label">OpenID Connect Discovery Document</label> <label class="form-label">OpenID Connect Discovery Document</label>
<div class="input-group mt-2"> <div class="input-group mt-2">
<input type="text" <input type="text" disabled value="{{ URL + "/.well-known/openid-configuration" }}" class="form-control">
disabled
value="{{ URL + "/.well-known/openid-configuration" }}"
class="form-control">
<span class="input-group-append"> <span class="input-group-append">
<button data-clipboard-text="{{ URL + "/.well-known/openid-configuration" }}" <button data-clipboard-text="{{ URL + "/.well-known/openid-configuration" }}" class="clipboard btn btn-primary" type="button">
class="clipboard btn btn-primary"
type="button">
<i class="fe fe-clipboard"></i> <i class="fe fe-clipboard"></i>
</button> </button>
</span> </span>
@ -23,14 +18,9 @@
<div class="form-group"> <div class="form-group">
<label class="form-label">Authorization endpoint</label> <label class="form-label">Authorization endpoint</label>
<div class="input-group mt-2"> <div class="input-group mt-2">
<input type="text" <input type="text" disabled value="{{ URL + "/oauth2/authorize" }}" class="form-control">
disabled
value="{{ URL + "/oauth2/authorize" }}"
class="form-control">
<span class="input-group-append"> <span class="input-group-append">
<button data-clipboard-text="{{ URL + "/oauth2/authorize" }}" <button data-clipboard-text="{{ URL + "/oauth2/authorize" }}" class="clipboard btn btn-primary" type="button">
class="clipboard btn btn-primary"
type="button">
<i class="fe fe-clipboard"></i> <i class="fe fe-clipboard"></i>
</button> </button>
</span> </span>
@ -39,14 +29,9 @@
<div class="form-group"> <div class="form-group">
<label class="form-label">Token endpoint</label> <label class="form-label">Token endpoint</label>
<div class="input-group mt-2"> <div class="input-group mt-2">
<input type="text" <input type="text" disabled value="{{ URL + "/oauth2/token" }}" class="form-control">
disabled
value="{{ URL + "/oauth2/token" }}"
class="form-control">
<span class="input-group-append"> <span class="input-group-append">
<button data-clipboard-text="{{ URL + "/oauth2/token" }}" <button data-clipboard-text="{{ URL + "/oauth2/token" }}" class="clipboard btn btn-primary" type="button">
class="clipboard btn btn-primary"
type="button">
<i class="fe fe-clipboard"></i> <i class="fe fe-clipboard"></i>
</button> </button>
</span> </span>
@ -55,14 +40,9 @@
<div class="form-group"> <div class="form-group">
<label class="form-label">UserInfo endpoint</label> <label class="form-label">UserInfo endpoint</label>
<div class="input-group mt-2"> <div class="input-group mt-2">
<input type="text" <input type="text" disabled value="{{ URL + "/oauth2/userinfo" }}" class="form-control">
disabled
value="{{ URL + "/oauth2/userinfo" }}"
class="form-control">
<span class="input-group-append"> <span class="input-group-append">
<button data-clipboard-text="{{ URL + "/oauth2/userinfo" }}" <button data-clipboard-text="{{ URL + "/oauth2/userinfo" }}" class="clipboard btn btn-primary" type="button">
class="clipboard btn btn-primary"
type="button">
<i class="fe fe-clipboard"></i> <i class="fe fe-clipboard"></i>
</button> </button>
</span> </span>

View file

@ -6,7 +6,7 @@
<h1 class="h2">Referral</h1> <h1 class="h2">Referral</h1>
<div> <div>
If you are in the If you are in the
<a href="{{ url_for('dashboard.referral_route') }}">referral</a> <a href="{{ url_for("dashboard.referral_route") }}">referral</a>
program, you can attach a program, you can attach a
referral to this website. referral to this website.
Any SimpleLogin sign up thanks to the SIWSL on your website will be counted towards this referral. Any SimpleLogin sign up thanks to the SIWSL on your website will be counted towards this referral.
@ -17,17 +17,9 @@
<select class="form-control" name="referral-id" id="client-select"> <select class="form-control" name="referral-id" id="client-select">
{% for referral in current_user.referrals %} {% for referral in current_user.referrals %}
<option value="{{ referral.id }}" <option value="{{ referral.id }}" {% if client.referral_id == referral.id %}selected{% endif %}>{{ referral.name }}</option>
{% if client.referral_id == referral.id %} selected{% endif %}>
{{ referral.name }}
</option>
{% endfor %} {% endfor %}
{% if client.referral_id is none %} {% if client.referral_id is none %}<option value="" selected>No referral selected</option>{% endif %}
<option value="" selected>
No referral selected
</option>
{% endif %}
</select> </select>
</div> </div>
<input type="submit" class="btn btn-primary" value="Update"> <input type="submit" class="btn btn-primary" value="Update">

View file

@ -18,9 +18,7 @@
How to use <i class="fe fe-chevrons-down"></i> How to use <i class="fe fe-chevrons-down"></i>
</a> </a>
</h1> </h1>
<div class="alert alert-primary collapse {% if not clients %} show{% endif %}" <div class="alert alert-primary collapse {% if not clients %}show{% endif %}" id="howtouse" role="alert">
id="howtouse"
role="alert">
If you want to integrate SIWSL into your website, If you want to integrate SIWSL into your website,
this page is for you. this page is for you.
<br /> <br />
@ -28,14 +26,9 @@
If you are using a CMS or any system that supports a OpenID Connect plugin, you can just point If you are using a CMS or any system that supports a OpenID Connect plugin, you can just point
it to SimpleLogin OpenID Configuration endpoint 👇 it to SimpleLogin OpenID Configuration endpoint 👇
<div class="input-group mt-2"> <div class="input-group mt-2">
<input type="text" <input type="text" disabled value="{{ URL + "/.well-known/openid-configuration" }}" class="form-control">
disabled
value="{{ URL + "/.well-known/openid-configuration" }}"
class="form-control">
<span class="input-group-append"> <span class="input-group-append">
<button data-clipboard-text="{{ URL + "/.well-known/openid-configuration" }}" <button data-clipboard-text="{{ URL + "/.well-known/openid-configuration" }}" class="clipboard btn btn-primary" type="button">
class="clipboard btn btn-primary"
type="button">
<i class="fe fe-clipboard"></i> <i class="fe fe-clipboard"></i>
</button> </button>
</span> </span>
@ -46,7 +39,7 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="btn-group" role="group" aria-label="Basic example"> <div class="btn-group" role="group" aria-label="Basic example">
<a href="{{ url_for('developer.new_client') }}" class="btn btn-primary">New website</a> <a href="{{ url_for("developer.new_client") }}" class="btn btn-primary">New website</a>
<a href="https://simplelogin.io/docs/siwsl/app/" <a href="https://simplelogin.io/docs/siwsl/app/"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"

View file

@ -2,14 +2,14 @@
<p style="font-size: 16px; <p style="font-size: 16px;
line-height: 1.625; line-height: 1.625;
color: #51545E; color: #51545E;
margin: .4em 0 1.1875em;">{{ text }}</p> margin: .4em 0 1.1875em">{{ text }}</p>
{% endmacro %} {% endmacro %}
<!-- To be used instead of render_text, much better! --> <!-- To be used instead of render_text, much better! -->
{% macro text() %} {% macro text() %}
<p style="font-size: 16px; <p style="font-size: 16px;
line-height: 1.625; line-height: 1.625;
color: #51545E; color: #51545E;
margin: .4em 0 1.1875em;">{{ caller() }}</p> margin: .4em 0 1.1875em">{{ caller() }}</p>
{% endmacro %} {% endmacro %}
{% macro render_button(button_text, link) %} {% macro render_button(button_text, link) %}
<!-- Action --> <!-- Action -->
@ -25,12 +25,12 @@
-premailer-cellspacing: 0; -premailer-cellspacing: 0;
text-align: center; text-align: center;
margin: 30px auto; margin: 30px auto;
padding: 0;"> padding: 0">
<tr> <tr>
<td align="center" <td align="center"
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px;"> font-size: 16px">
<!-- Border based button <!-- Border based button
https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design --> https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
<table width="100%" <table width="100%"
@ -42,7 +42,7 @@ https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
<td align="center" <td align="center"
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px;"> font-size: 16px">
<a href="{{ link }}" <a href="{{ link }}"
class="f-fallback button" class="f-fallback button"
target="_blank" target="_blank"
@ -57,9 +57,7 @@ https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
border-radius: 3px; border-radius: 3px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16); box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
-webkit-text-size-adjust: none; -webkit-text-size-adjust: none;
box-sizing: border-box;"> box-sizing: border-box">{{ button_text }}</a>
{{ button_text }}
</a>
</td> </td>
</tr> </tr>
</table> </table>
@ -75,25 +73,23 @@ https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
padding-top: 25px; padding-top: 25px;
border-top-width: 1px; border-top-width: 1px;
border-top-color: #EAEAEC; border-top-color: #EAEAEC;
border-top-style: solid;"> border-top-style: solid">
<tr> <tr>
<td style="word-break: break-word; <td style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px;"> font-size: 16px">
<p class="f-fallback sub" <p class="f-fallback sub"
style="font-size: 13px; style="font-size: 13px;
line-height: 1.625; line-height: 1.625;
color: #51545E; color: #51545E;
margin: .4em 0 1.1875em;"> margin: .4em 0 1.1875em">
If youre having trouble with the button above, copy and paste the URL below into your web browser. If youre having trouble with the button above, copy and paste the URL below into your web browser.
</p> </p>
<p class="f-fallback sub" <p class="f-fallback sub"
style="font-size: 13px; style="font-size: 13px;
line-height: 1.625; line-height: 1.625;
color: #51545E; color: #51545E;
margin: .4em 0 1.1875em;"> margin: .4em 0 1.1875em">{{ link }}</p>
{{ link }}
</p>
</td> </td>
</tr> </tr>
</table> </table>
@ -104,14 +100,14 @@ https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
cellpadding="0" cellpadding="0"
cellspacing="0" cellspacing="0"
role="presentation" role="presentation"
style="margin: 0 0 21px;"> style="margin: 0 0 21px">
<tr> <tr>
<td class="attributes_content" <td class="attributes_content"
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px; font-size: 16px;
background-color: #F4F4F7; background-color: #F4F4F7;
padding: 16px;" padding: 16px"
bgcolor="#F4F4F7"> bgcolor="#F4F4F7">
<table width="100%" cellpadding="0" cellspacing="0" role="presentation"> <table width="100%" cellpadding="0" cellspacing="0" role="presentation">
{% for part in parts %} {% for part in parts %}
@ -121,7 +117,7 @@ https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px; font-size: 16px;
padding: 0;"> padding: 0">
<div class="f-fallback"> <div class="f-fallback">
{{ part }} {{ part }}
<br /> <br />

View file

@ -1,5 +1,5 @@
{% from "_emailhelpers.html" import render_text, text, render_button, raw_url, grey_section, section %} {% from "_emailhelpers.html" import render_text, text, render_button, raw_url, grey_section, section %}
<!doctype html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" <html xmlns="http://www.w3.org/1999/xhtml"
xmlns:v="urn:schemas-microsoft-com:vml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"> xmlns:o="urn:schemas-microsoft-com:office:office">
@ -8,7 +8,7 @@
<!--[if gte mso 15]> <!--[if gte mso 15]>
<xml> <xml>
<o:OfficeDocumentSettings> <o:OfficeDocumentSettings>
<o:AllowPNG/> <o:AllowPNG />
<o:PixelsPerInch>96</o:PixelsPerInch> <o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings> </o:OfficeDocumentSettings>
</xml> </xml>
@ -504,7 +504,7 @@
padding: 0; padding: 0;
width: 100%; width: 100%;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;"> -webkit-text-size-adjust: 100%">
<!--[if !gte mso 9]><!----><span class="mcnPreviewText" <!--[if !gte mso 9]><!----><span class="mcnPreviewText"
style="display:none; style="display:none;
font-size:0px; font-size:0px;
@ -514,7 +514,7 @@
opacity:0; opacity:0;
overflow:hidden; overflow:hidden;
visibility:hidden; visibility:hidden;
mso-hide:all;"></span><!--<![endif]--> mso-hide:all"></span><!--<![endif]-->
<center> <center>
<table align="center" <table align="center"
border="0" border="0"
@ -531,7 +531,7 @@
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
width: 100%;"> width: 100%">
<tr> <tr>
<td align="center" <td align="center"
valign="top" valign="top"
@ -542,7 +542,7 @@
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 8px; padding: 8px;
width: 100%;"> width: 100%">
<!-- BEGIN TEMPLATE // --> <!-- BEGIN TEMPLATE // -->
<!--[if (gte mso 9)|(IE)]> <!--[if (gte mso 9)|(IE)]>
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600" style="width:600px;"><tr><td align="center" valign="top" width="600" style="width:600px;"> <table align="center" border="0" cellspacing="0" cellpadding="0" width="600" style="width:600px;"><tr><td align="center" valign="top" width="600" style="width:600px;">
@ -557,13 +557,13 @@
mso-table-rspace: 0pt; mso-table-rspace: 0pt;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
max-width: 600px !important;"> max-width: 600px !important">
<tr> <tr>
<td valign="top" <td valign="top"
id="templateHeader" id="templateHeader"
style="mso-line-height-rule: exactly; style="mso-line-height-rule: exactly;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;"> -webkit-text-size-adjust: 100%">
<table border="0" <table border="0"
cellpadding="0" cellpadding="0"
cellspacing="0" cellspacing="0"
@ -574,14 +574,14 @@
mso-table-lspace: 0pt; mso-table-lspace: 0pt;
mso-table-rspace: 0pt; mso-table-rspace: 0pt;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;"> -webkit-text-size-adjust: 100%">
<tbody class="mcnImageBlockOuter"> <tbody class="mcnImageBlockOuter">
<tr> <tr>
<td valign="top" <td valign="top"
style="padding: 16px; style="padding: 16px;
mso-line-height-rule: exactly; mso-line-height-rule: exactly;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;" -webkit-text-size-adjust: 100%"
class="mcnImageBlockInner"> class="mcnImageBlockInner">
<table align="left" <table align="left"
width="100%" width="100%"
@ -594,7 +594,7 @@
mso-table-lspace: 0pt; mso-table-lspace: 0pt;
mso-table-rspace: 0pt; mso-table-rspace: 0pt;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;"> -webkit-text-size-adjust: 100%">
<tbody> <tbody>
<tr> <tr>
<td class="mcnImageContent" <td class="mcnImageContent"
@ -603,13 +603,22 @@
text-align: center; text-align: center;
mso-line-height-rule: exactly; mso-line-height-rule: exactly;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;"> -webkit-text-size-adjust: 100%">
<a href="https://proton.me/" target="_blank" style=""> <a href="https://proton.me/" target="_blank" style="">
<img align="center" <img align="center"
alt="Proton" alt="Proton"
src="{{ URL }}/static/logo-proton.png" src="{{ URL }}/static/logo-proton.png"
width="190" width="190"
style="width:35.4477%; max-width: 380px; padding-bottom: 0; display: inline !important; vertical-align: bottom; border: 0; height: auto; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; "> style="width:35.4477%;
max-width: 380px;
padding-bottom: 0;
display: inline !important;
vertical-align: bottom;
border: 0;
height: auto;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic">
</a> </a>
</td> </td>
</tr> </tr>
@ -624,7 +633,9 @@
<tr> <tr>
<td valign="top" <td valign="top"
id="templateBody" id="templateBody"
style="mso-line-height-rule: exactly; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; "> style="mso-line-height-rule: exactly;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%">
{% block greeting %}{% endblock %} {% block greeting %}{% endblock %}
{% block content %}{% endblock %} {% block content %}{% endblock %}
<!-- Sub copy --> <!-- Sub copy -->

View file

@ -423,7 +423,7 @@
.f-fallback { .f-fallback {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
} }
</style> </style>
<![endif]--> <![endif]-->
<style type="text/css" rel="stylesheet" media="all"> <style type="text/css" rel="stylesheet" media="all">
body { body {
@ -449,7 +449,7 @@
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
background-color: #F2F4F6; background-color: #F2F4F6;
color: #51545E; color: #51545E;
margin: 0;" margin: 0"
bgcolor="#F2F4F6"> bgcolor="#F2F4F6">
<span class="preheader" <span class="preheader"
style="display: none !important; style="display: none !important;
@ -460,7 +460,7 @@
max-height: 0; max-height: 0;
max-width: 0; max-width: 0;
opacity: 0; opacity: 0;
overflow: hidden;">{{ pre_header }}</span> overflow: hidden">{{ pre_header }}</span>
<table class="email-wrapper" <table class="email-wrapper"
width="100%" width="100%"
cellpadding="0" cellpadding="0"
@ -472,13 +472,13 @@
-premailer-cellspacing: 0; -premailer-cellspacing: 0;
background-color: #F2F4F6; background-color: #F2F4F6;
margin: 0; margin: 0;
padding: 0;" padding: 0"
bgcolor="#F2F4F6"> bgcolor="#F2F4F6">
<tr> <tr>
<td align="center" <td align="center"
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px;"> font-size: 16px">
<table class="email-content" <table class="email-content"
width="100%" width="100%"
cellpadding="0" cellpadding="0"
@ -489,14 +489,14 @@
-premailer-cellpadding: 0; -premailer-cellpadding: 0;
-premailer-cellspacing: 0; -premailer-cellspacing: 0;
margin: 0; margin: 0;
padding: 0;"> padding: 0">
<tr> <tr>
<td class="email-masthead" <td class="email-masthead"
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px; font-size: 16px;
text-align: center; text-align: center;
padding: 25px 0;" padding: 25px 0"
align="center"> align="center">
<a href="{{ LANDING_PAGE_URL }}" <a href="{{ LANDING_PAGE_URL }}"
class="f-fallback email-masthead_name" class="f-fallback email-masthead_name"
@ -504,7 +504,7 @@
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
text-decoration: none; text-decoration: none;
text-shadow: 0 1px 0 white;"> text-shadow: 0 1px 0 white">
{% block logo %}<img src="{{ URL }}/static/logo.png" style="width: 150px; margin: auto">{% endblock %} {% block logo %}<img src="{{ URL }}/static/logo.png" style="width: 150px; margin: auto">{% endblock %}
</a> </a>
</td> </td>
@ -523,7 +523,7 @@
width: 100%; width: 100%;
-premailer-width: 100%; -premailer-width: 100%;
-premailer-cellpadding: 0; -premailer-cellpadding: 0;
-premailer-cellspacing: 0;"> -premailer-cellspacing: 0">
<table class="email-body_inner" <table class="email-body_inner"
align="center" align="center"
width="750" width="750"
@ -536,7 +536,7 @@
-premailer-cellspacing: 0; -premailer-cellspacing: 0;
background-color: #FFFFFF; background-color: #FFFFFF;
margin: 0 auto; margin: 0 auto;
padding: 0;" padding: 0"
bgcolor="#FFFFFF"> bgcolor="#FFFFFF">
<!-- Body content --> <!-- Body content -->
<tr> <tr>
@ -544,7 +544,7 @@
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px; font-size: 16px;
padding: 30px;"> padding: 30px">
<div class="f-fallback"> <div class="f-fallback">
{% block greeting %}{% endblock %} {% block greeting %}{% endblock %}
{% block content %}{% endblock %} {% block content %}{% endblock %}
@ -559,7 +559,7 @@
<tr> <tr>
<td style="word-break: break-word; <td style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px;"> font-size: 16px">
<table class="email-footer" <table class="email-footer"
align="center" align="center"
width="750" width="750"
@ -572,20 +572,20 @@
-premailer-cellspacing: 0; -premailer-cellspacing: 0;
text-align: center; text-align: center;
margin: 0 auto; margin: 0 auto;
padding: 0;"> padding: 0">
<tr> <tr>
<td class="content-cell" <td class="content-cell"
align="center" align="center"
style="word-break: break-word; style="word-break: break-word;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 16px; font-size: 16px;
padding: 30px;"> padding: 30px">
<p class="f-fallback sub align-center" <p class="f-fallback sub align-center"
style="font-size: 13px; style="font-size: 13px;
line-height: 1.625; line-height: 1.625;
text-align: center; text-align: center;
color: #A8AAAF; color: #A8AAAF;
margin: .4em 0 1.1875em;" margin: .4em 0 1.1875em"
align="center"> align="center">
© {{ YEAR }} SimpleLogin - a Proton product. All rights reserved. © {{ YEAR }} SimpleLogin - a Proton product. All rights reserved.
<br /> <br />
@ -597,7 +597,7 @@
style="font-size: 13px; style="font-size: 13px;
line-height: 1.625; line-height: 1.625;
text-align: center; text-align: center;
margin: .4em 0 1.1875em;"> margin: .4em 0 1.1875em">
<a href="{{ unsubscribe_oneclick }}">Unsubscribe from our newsletter</a> <a href="{{ unsubscribe_oneclick }}">Unsubscribe from our newsletter</a>
</p> </p>
{% endif %} {% endif %}
@ -606,7 +606,7 @@
line-height: 1.625; line-height: 1.625;
text-align: center; text-align: center;
color: #A8AAAF; color: #A8AAAF;
margin: .4em 0 1.1875em;" margin: .4em 0 1.1875em"
align="center"> align="center">
<a href="https://app.simplelogin.io/dashboard/support">Do you have a question?</a> <a href="https://app.simplelogin.io/dashboard/support">Do you have a question?</a>
</p> </p>

View file

@ -4,10 +4,10 @@
{{ render_text("Hi") }} {{ render_text("Hi") }}
{{ render_text("Our most requested feature is finally ready: you can now add several <b>real</b> email addresses into SimpleLogin {{ render_text("Our most requested feature is finally ready: you can now add several <b>real</b> email addresses into SimpleLogin
and choose which one to use when creating aliases!") }} and choose which one to use when creating aliases!") }}
{{ render_text("A real email address is called <b>mailbox</b> in SimpleLogin.") }} {{ render_text("A real email address is called <b>mailbox</b> in SimpleLogin.") }}
{{ render_text('This feature is particularly useful if you have several email addresses, {{ render_text('This feature is particularly useful if you have several email addresses,
maybe for different uses: a Gmail account for social networks & forums, a Prontonmail account for professional emails, etc.') }} maybe for different uses: a Gmail account for social networks & forums, a Prontonmail account for professional emails, etc.') }}
<img src="https://simplelogin.io/blog/mailbox-gmail.png" <img src="https://simplelogin.io/blog/mailbox-gmail.png"
alt="Mailbox Gmail"> alt="Mailbox Gmail">
<img src="https://simplelogin.io/blog/mailbox-protonmail.png" <img src="https://simplelogin.io/blog/mailbox-protonmail.png"
@ -18,9 +18,9 @@
{{ render_text("You can also change the owning mailbox for an existing alias.") }} {{ render_text("You can also change the owning mailbox for an existing alias.") }}
{{ render_text("The mailbox doesn't have to be your personal email: you can also create aliases for your friend by adding his/her email as a mailbox.") }} {{ render_text("The mailbox doesn't have to be your personal email: you can also create aliases for your friend by adding his/her email as a mailbox.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ render_text('<strong>P.S.</strong> Need immediate help getting started? Just reply to this email, the SimpleLogin support team is always ready to help!.') }} {{ render_text("<strong>P.S.</strong> Need immediate help getting started? Just reply to this email, the SimpleLogin support team is always ready to help!.") }}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -4,127 +4,127 @@
{{ render_text("Hi") }} {{ render_text("Hi") }}
{% call text() %} {% call text() %}
Son from SimpleLogin here. I hope you are doing well and are staying at home in this difficult time. By the way I'm Son from SimpleLogin here. I hope you are doing well and are staying at home in this difficult time. By the way I'm
writing this newsletter from my couch with my cats proofreading the text :). writing this newsletter from my couch with my cats proofreading the text :).
<br /> <br />
Please find below some of our latest news. Please find below some of our latest news.
<br /> <br />
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
1) <b>Mobile apps</b> 1) <b>Mobile apps</b>
<br /> <br />
<br /> <br />
<img src="https://simplelogin.io/blog/devices.png" style="max-width: 100%"> <img src="https://simplelogin.io/blog/devices.png" style="max-width: 100%">
<br /> <br />
<br /> <br />
Now you can quickly create aliases on-the-go with SimpleLogin Android and iOS app, Now you can quickly create aliases on-the-go with SimpleLogin Android and iOS app,
thanks to our mobile guy Thanh-Nhon! thanks to our mobile guy Thanh-Nhon!
<br /> <br />
Download the Android app on Download the Android app on
<a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Play Store</a> <a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Play Store</a>
and the iOS app on and the iOS app on
<a href="https://apps.apple.com/app/id1494359858">App Store</a> <a href="https://apps.apple.com/app/id1494359858">App Store</a>
. .
<br /> <br />
With the release of the mobile apps, SimpleLogin now covers most major platforms: With the release of the mobile apps, SimpleLogin now covers most major platforms:
<br /> <br />
- Desktop with SimpleLogin web app or Chrome, Firefox and Safari extension - Desktop with SimpleLogin web app or Chrome, Firefox and Safari extension
<br /> <br />
- Mobile with Android and iOS app - Mobile with Android and iOS app
<br /> <br />
The code is of course open-source and available on our The code is of course open-source and available on our
<a href="https://github.com/simple-login/">Github</a> <a href="https://github.com/simple-login/">Github</a>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
2) <b>Dark mode</b> 2) <b>Dark mode</b>
<br /> <br />
<br /> <br />
<img src="https://simplelogin.io/blog/dark-mode.gif" style="width: 100%"> <img src="https://simplelogin.io/blog/dark-mode.gif" style="width: 100%">
<br /> <br />
<br /> <br />
You have asked for it and now the dark mode is finally available, kudos to Dung - our full-stack guy. You have asked for it and now the dark mode is finally available, kudos to Dung - our full-stack guy.
<br /> <br />
You can finally enjoy using SimpleLogin in the dark. You can finally enjoy using SimpleLogin in the dark.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
3) <b>Alias name, new UI, security page, new policy privacy</b> 3) <b>Alias name, new UI, security page, new policy privacy</b>
<br /> <br />
<br /> <br />
<img src="https://simplelogin.io/blog/new-ui.gif" style="width: 100%"> <img src="https://simplelogin.io/blog/new-ui.gif" style="width: 100%">
<br /> <br />
<br /> <br />
You might have noticed that the web UI is now more compact: the web app has undergone a remake You might have noticed that the web UI is now more compact: the web app has undergone a remake
to make it more responsive for usual actions like enabling/disabling an alias, updating alias note, etc. to make it more responsive for usual actions like enabling/disabling an alias, updating alias note, etc.
<br /> <br />
You can set a name for your alias too: this name is used when you send emails or reply from your alias. You can set a name for your alias too: this name is used when you send emails or reply from your alias.
<br /> <br />
We have also created a new We have also created a new
<a href="https://simplelogin.io/security/">security page</a> <a href="https://simplelogin.io/security/">security page</a>
that goes into the technical that goes into the technical
details of SimpleLogin. details of SimpleLogin.
Our Our
<a href="https://simplelogin.io/privacy/">privacy page</a> <a href="https://simplelogin.io/privacy/">privacy page</a>
is also rewritten from scratch: nothing changes about is also rewritten from scratch: nothing changes about
your data protection your data protection
but the page is more clear and detailed now. but the page is more clear and detailed now.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
4) <b>Facebook, Google, Github login deprecation</b> 4) <b>Facebook, Google, Github login deprecation</b>
<br /> <br />
We have decided to deprecate those social login options because of several reasons: We have decided to deprecate those social login options because of several reasons:
<br /> <br />
- Privacy: every time you sign in using one of these methods, the respective company knows and - Privacy: every time you sign in using one of these methods, the respective company knows and
we have no information on what they do with this data. we have no information on what they do with this data.
<br /> <br />
- Not fully open-standard compatible: these platforms enjoy their monopolies and - Not fully open-standard compatible: these platforms enjoy their monopolies and
don't play well with open standards like OAuth2/OpenID: in fact, implementations on mobile of these social login don't play well with open standards like OAuth2/OpenID: in fact, implementations on mobile of these social login
require their SDK that we refuse to add because of privacy concern. require their SDK that we refuse to add because of privacy concern.
<br /> <br />
- Uniform experiences for all users: to have these social login in our iOS app, we need to support "Sign in with - Uniform experiences for all users: to have these social login in our iOS app, we need to support "Sign in with
Apple" that isn't broadly available for Android users. Apple" that isn't broadly available for Android users.
Again, another big tech enjoying its monopoly. Again, another big tech enjoying its monopoly.
<br /> <br />
If you happen to use one of these social login options, please create a password for your account on the If you happen to use one of these social login options, please create a password for your account on the
<a href="{{ URL }}/dashboard/setting">Setting page</a> <a href="{{ URL }}/dashboard/setting">Setting page</a>
<br /> <br />
You can still sign in using these social login until 2020-05-31. After this date, they will be removed. You can still sign in using these social login until 2020-05-31. After this date, they will be removed.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
5) <b>WebAuthn (Beta)</b> 5) <b>WebAuthn (Beta)</b>
<br /> <br />
Thanks to Raymond, a user of SimpleLogin, the WebAuthn is now available in Beta. Thanks to Raymond, a user of SimpleLogin, the WebAuthn is now available in Beta.
Please reply to this email if you want to try this out. Please reply to this email if you want to try this out.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
<hr style="margin: 10px;"> <hr style="margin: 10px;">
On behalf of the team, I want to say thank you to all users who have helped to improve SimpleLogin code On behalf of the team, I want to say thank you to all users who have helped to improve SimpleLogin code
and even contribute important features. and even contribute important features.
That means a lot to us as SimpleLogin is after all an open-source project. That means a lot to us as SimpleLogin is after all an open-source project.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
That's all for today. If you want to follow all our latest features, you can follow our That's all for today. If you want to follow all our latest features, you can follow our
<a href="https://twitter.com/simplelogin">Twitter</a> <a href="https://twitter.com/simplelogin">Twitter</a>
or join our or join our
<a href="https://www.reddit.com/r/Simplelogin/">Reddit</a> <a href="https://www.reddit.com/r/Simplelogin/">Reddit</a>
or subscribe to our or subscribe to our
<a href="https://feed43.com/simplelogin.xml">RSS feed</a> <a href="https://feed43.com/simplelogin.xml">RSS feed</a>
. .
<br /> <br />
Now back to coding :). Now back to coding :).
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
Son. Son.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -5,8 +5,8 @@
{{ render_text("Hi") }} {{ render_text("Hi") }}
{{ render_text("If you happen to use Gmail, Yahoo, Outlook, etc, do you know these services can read your emails?") }} {{ render_text("If you happen to use Gmail, Yahoo, Outlook, etc, do you know these services can read your emails?") }}
{{ render_text("If you want to keep your emails only readable by you, Pretty Good Privacy (PGP) is maybe the solution.") }} {{ render_text("If you want to keep your emails only readable by you, Pretty Good Privacy (PGP) is maybe the solution.") }}
{{ render_text('Highly recommended, open source and free, PGP is unfortunately not widely supported. However with SimpleLogin most recent PGP support, you can now enable PGP on emails sent to your aliases easily.') }} {{ render_text("Highly recommended, open source and free, PGP is unfortunately not widely supported. However with SimpleLogin most recent PGP support, you can now enable PGP on emails sent to your aliases easily.") }}
{{ render_text('Without PGP the emails sent to an alias are forwarded by SimpleLogin as-is to your mailbox, leaving anyone in-between or your email service able to read your emails:') }} {{ render_text("Without PGP the emails sent to an alias are forwarded by SimpleLogin as-is to your mailbox, leaving anyone in-between or your email service able to read your emails:") }}
<img src="https://simplelogin.io/blog/without-pgp.png" <img src="https://simplelogin.io/blog/without-pgp.png"
alt="Without PGP" alt="Without PGP"
style="max-width: 100%"> style="max-width: 100%">
@ -18,13 +18,13 @@
{{ render_text("You can create and manage your PGP keys when adding or editing your mailboxes. Check it out on your mailbox dashboard.") }} {{ render_text("You can create and manage your PGP keys when adding or editing your mailboxes. Check it out on your mailbox dashboard.") }}
{{ render_button("Add your PGP key", URL ~ "/dashboard/mailbox") }} {{ render_button("Add your PGP key", URL ~ "/dashboard/mailbox") }}
{{ render_text("Our next important feature is the coming of an iOS app. If you use iPhone or iPad want to help us testing out the app, please reply to this email so we can add you into the TestFlight program. {{ render_text("Our next important feature is the coming of an iOS app. If you use iPhone or iPad want to help us testing out the app, please reply to this email so we can add you into the TestFlight program.
") }} ") }}
{{ render_text("For Android users, don't worry: the Android version is already in progress. {{ render_text("For Android users, don't worry: the Android version is already in progress.
") }} ") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ render_text('<strong>P.S.</strong> Need immediate help getting started? Just reply to this email, the SimpleLogin support team is always ready to help!.') }} {{ render_text("<strong>P.S.</strong> Need immediate help getting started? Just reply to this email, the SimpleLogin support team is always ready to help!.") }}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -17,7 +17,7 @@
line-height: 160%; line-height: 160%;
padding-top: 25px; padding-top: 25px;
color: #000000; color: #000000;
font-family: sans-serif;" font-family: sans-serif"
class="paragraph"> class="paragraph">
This email is sent to {{ user.email }}. This email is sent to {{ user.email }}.
Unsubscribe on Unsubscribe on
@ -28,16 +28,16 @@
{{ render_text("Hi") }} {{ render_text("Hi") }}
{{ render_text("If you use Safari on a MacBook or iMac, you should check out our new Safari extension.") }} {{ render_text("If you use Safari on a MacBook or iMac, you should check out our new Safari extension.") }}
{{ render_text('It can be installed on {{ render_text('It can be installed on
<a href="https://apps.apple.com/app/id6475835429">App Store</a> <a href="https://apps.apple.com/app/id6475835429">App Store</a>
. Its code is available on . Its code is available on
<a href="https://github.com/simple-login/mac-app">GitHub</a> <a href="https://github.com/simple-login/mac-app">GitHub</a>
.') }} .') }}
{{ render_text(' {{ render_text('
<img src="https://static.simplelogin.io/safari-extension.png" <img src="https://static.simplelogin.io/safari-extension.png"
style="max-width: 600px"> style="max-width: 600px">
') }} ') }}
{{ render_text('See our annoucement post for more information on this feature {{ render_text('See our annoucement post for more information on this feature
<a href="https://simplelogin.io/blog/safari-extension/">Introducing Safari extension</a> <a href="https://simplelogin.io/blog/safari-extension/">Introducing Safari extension</a>
.') }} .') }}
{{ render_text("As usual, let me know if you have any question by replying to this email.") }} {{ render_text("As usual, let me know if you have any question by replying to this email.") }}
{% endblock %} {% endblock %}

View file

@ -3,30 +3,30 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Download SimpleLogin browser extensions and mobile apps to create aliases on-the-fly.</h1> <h1>Download SimpleLogin browser extensions and mobile apps to create aliases on-the-fly.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you want to quickly create aliases <b>without</b> going to SimpleLogin website, you can do that with SimpleLogin If you want to quickly create aliases <b>without</b> going to SimpleLogin website, you can do that with SimpleLogin
<a href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">Chrome</a> <a href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">Chrome</a>
(or other Chromium-based browsers like Brave or Vivaldi), (or other Chromium-based browsers like Brave or Vivaldi),
<a href="https://addons.mozilla.org/firefox/addon/simplelogin/">Firefox</a> <a href="https://addons.mozilla.org/firefox/addon/simplelogin/">Firefox</a>
and and
<a href="https://apps.apple.com/app/id6475835429 ">Safari</a> <a href="https://apps.apple.com/app/id6475835429 ">Safari</a>
extension. extension.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
You can also manage your aliases using SimpleLogin You can also manage your aliases using SimpleLogin
<a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Android App</a> <a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Android App</a>
or or
<a href="https://apps.apple.com/app/id1494359858">iOS app</a> <a href="https://apps.apple.com/app/id1494359858">iOS app</a>
. .
{% endcall %} {% endcall %}
<img src="https://simplelogin.io/images/everywhere.png" <img src="https://simplelogin.io/images/everywhere.png"
alt="Available Everywhere" alt="Available Everywhere"
style="max-width: 100%;"> style="max-width: 100%">
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -3,32 +3,34 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Add other mailboxes to SimpleLogin.</h1> <h1>Add other mailboxes to SimpleLogin.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you have several email inboxes, say Gmail and Proton Mail, If you have several email inboxes, say Gmail and Proton Mail,
you can add them into SimpleLogin as <b>mailboxes</b>. you can add them into SimpleLogin as <b>mailboxes</b>.
{% endcall %} {% endcall %}
<img src="https://simplelogin.io/images/multiple-mailboxes.png" <img src="https://simplelogin.io/images/multiple-mailboxes.png"
alt="Multiple Mailboxes" alt="Multiple Mailboxes"
style="max-width: 100%; margin: auto; border: 1px solid"> style="max-width: 100%;
{% call text() %} margin: auto;
When creating an alias, you can choose the mailbox(es) that border: 1px solid">
<b>owns</b> this alias, meaning: {% call text() %}
<br /> When creating an alias, you can choose the mailbox(es) that
1. Emails sent to this alias are forwarded to the owning mailbox(es). <b>owns</b> this alias, meaning:
<br /> <br />
2. The owning mailbox(es) can send emails from this alias. 1. Emails sent to this alias are forwarded to the owning mailbox(es).
{% endcall %} <br />
2. The owning mailbox(es) can send emails from this alias.
{% endcall %}
{% call text() %} {% call text() %}
Please note that adding additional mailboxes is only available in the Premium plan. Please note that adding additional mailboxes is only available in the Premium plan.
{% endcall %} {% endcall %}
{{ render_button("Create mailbox", URL ~ "/dashboard/mailbox") }} {{ render_button("Create mailbox", URL ~ "/dashboard/mailbox") }}
{{ raw_url(URL ~ "/dashboard/mailbox") }} {{ raw_url(URL ~ "/dashboard/mailbox") }}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -3,32 +3,34 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Secure your emails with PGP.</h1> <h1>Secure your emails with PGP.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you use Gmail, Yahoo, Outlook, etc, you might want to use If you use Gmail, Yahoo, Outlook, etc, you might want to use
<a href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy">PGP</a> <a href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy">PGP</a>
(Pretty Good Privacy) (Pretty Good Privacy)
to make sure your emails can't be read by these email providers. to make sure your emails can't be read by these email providers.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Without PGP, emails are stored <b>in plaintext</b> leaving your email service able to read your emails. Without PGP, emails are stored <b>in plaintext</b> leaving your email service able to read your emails.
{% endcall %} {% endcall %}
<img src="https://simplelogin.io/blog/without-pgp.png" <img src="https://simplelogin.io/blog/without-pgp.png"
alt="Without PGP" alt="Without PGP"
style="max-width: 100%; margin-bottom: 10px"> style="max-width: 100%;
{% call text() %} margin-bottom: 10px">
With PGP enabled, SimpleLogin <b>encrypts</b> your emails with your public key before forwarding to your mailbox. {% call text() %}
{% endcall %} With PGP enabled, SimpleLogin <b>encrypts</b> your emails with your public key before forwarding to your mailbox.
{% endcall %}
<img src="https://simplelogin.io/blog/with-pgp.png" <img src="https://simplelogin.io/blog/with-pgp.png"
alt="Without PGP" alt="Without PGP"
style="max-width: 100%; margin-bottom: 20px"> style="max-width: 100%;
{{ render_button("Enable PGP on your mailbox", URL ~ "/dashboard/mailbox/" ~ user.default_mailbox_id) }} margin-bottom: 20px">
{{ raw_url(URL ~ "/dashboard/mailbox/" ~ user.default_mailbox_id) }} {{ render_button("Enable PGP on your mailbox", URL ~ "/dashboard/mailbox/" ~ user.default_mailbox_id) }}
{{ raw_url(URL ~ "/dashboard/mailbox/" ~ user.default_mailbox_id) }}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -3,46 +3,46 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Send emails from your alias.</h1> <h1>Send emails from your alias.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you want to reply to an email, just hit "Reply" If you want to reply to an email, just hit "Reply"
and the response will come from your alias. Your personal email address stays hidden. and the response will come from your alias. Your personal email address stays hidden.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
To send an email to a <b>new contact</b>, please follow the steps below. To send an email to a <b>new contact</b>, please follow the steps below.
You can also watch this You can also watch this
<a href="https://youtu.be/GN060XMt6Pc">Youtube video</a> <a href="https://youtu.be/GN060XMt6Pc">Youtube video</a>
that quickly walks you through the steps. that quickly walks you through the steps.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
1. Click the <b>Contacts</b> button on the alias you want to send emails from 1. Click the <b>Contacts</b> button on the alias you want to send emails from
<br /> <br />
<img src="https://simplelogin.io/docs/getting-started/send-email/contacts.png" <img src="https://simplelogin.io/docs/getting-started/send-email/contacts.png"
style="max-width: 500px"> style="max-width: 500px">
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
2. Enter your contact email, this will create a <b>reverse-alias</b> for the contact. 2. Enter your contact email, this will create a <b>reverse-alias</b> for the contact.
<br /> <br />
<img src="https://simplelogin.io/docs/getting-started/send-email/new-contact.png" <img src="https://simplelogin.io/docs/getting-started/send-email/new-contact.png"
style="max-width: 500px"> style="max-width: 500px">
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
3. Send the email to this reverse-alias <b>instead of the contact email</b>. 3. Send the email to this reverse-alias <b>instead of the contact email</b>.
<br /> <br />
<img src="https://simplelogin.io/docs/getting-started/send-email/reverse-alias.png" <img src="https://simplelogin.io/docs/getting-started/send-email/reverse-alias.png"
style="max-width: 500px"> style="max-width: 500px">
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
And voilà, your contact will receive this email sent from your alias! And voilà, your contact will receive this email sent from your alias!
Your real mailbox address will stay hidden. Your real mailbox address will stay hidden.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -4,57 +4,57 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
Welcome to SimpleLogin, a service developed by Proton to protect your email address! Welcome to SimpleLogin, a service developed by Proton to protect your email address!
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
This is the first email you receive via your <b>first alias</b> {{ to_address }} This is the first email you receive via your <b>first alias</b> {{ to_address }}
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
This alias is automatically created when you use SimpleLogin for the first time. This alias is automatically created when you use SimpleLogin for the first time.
Emails sent to it are forwarded to your Proton mailbox. Emails sent to it are forwarded to your Proton mailbox.
If you want to reply to an email, just hit "Reply" and the response will come from your alias. If you want to reply to an email, just hit "Reply" and the response will come from your alias.
Your personal email address stays hidden. Your personal email address stays hidden.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
To create new aliases, use the SimpleLogin browser extension (recommended) or web dashboard. To create new aliases, use the SimpleLogin browser extension (recommended) or web dashboard.
SimpleLogin is available on SimpleLogin is available on
<a href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">Chrome</a> <a href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">Chrome</a>
, ,
<a href="https://addons.mozilla.org/firefox/addon/simplelogin/">Firefox</a> <a href="https://addons.mozilla.org/firefox/addon/simplelogin/">Firefox</a>
and and
<a href="https://microsoftedge.microsoft.com/addons/detail/simpleloginreceive-sen/diacfpipniklenphgljfkmhinphjlfff"> <a href="https://microsoftedge.microsoft.com/addons/detail/simpleloginreceive-sen/diacfpipniklenphgljfkmhinphjlfff">
Edge Edge
</a> </a>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
SimpleLogin is also available on SimpleLogin is also available on
<a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Android</a> <a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Android</a>
and and
<a href="https://apps.apple.com/app/id1494359858">iOS</a> <a href="https://apps.apple.com/app/id1494359858">iOS</a>
so you can manage your aliases on the go. so you can manage your aliases on the go.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Note, if you are a paying Proton Mail user, you automatically receive the premium version of SimpleLogin. Note, if you are a paying Proton Mail user, you automatically receive the premium version of SimpleLogin.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
For any question or if you want to request a feature, please submit it on our <a href="https://github.com/simple-login/app/discussions">forum</a>. For any question or if you want to request a feature, please submit it on our <a href="https://github.com/simple-login/app/discussions">forum</a>.
You can also join our You can also join our
<a href="https://www.reddit.com/r/Simplelogin/">Reddit</a> <a href="https://www.reddit.com/r/Simplelogin/">Reddit</a>
or follow our or follow our
<a href="https://twitter.com/simple_login">Twitter</a> <a href="https://twitter.com/simple_login">Twitter</a>
. .
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -6,78 +6,78 @@
color: #333333; color: #333333;
font-size: 22px; font-size: 22px;
font-weight: bold; font-weight: bold;
text-align: left;" text-align: left"
align="left"> align="left">Welcome!</h1>
Welcome!
</h1>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if alias %} {% if alias %}
{% call text() %} {% call text() %}
This is the first email you receive via your <b>first alias</b> <em>{{ alias }}</em>. This is the first email you receive via your <b>first alias</b> <em>{{ alias }}</em>.
{% endcall %}
{% call text() %}
This alias is automatically created for receiving SimpleLogin news and tips.
<br />
In the next coming days, we'll send you 3 emails to help you get the best out of SimpleLogin.
<br />
Please
<a href="{{ URL + '/dashboard/setting#notification' }}">disable</a>
it if you don't need this.
{% endcall %}
{% endif %}
{% call text() %}
If you are using Firefox or a Chromium-browser like Chrome, Edge, Brave, you can
install our
<a href="https://addons.mozilla.org/firefox/addon/simplelogin/">Firefox add-on</a>
or
<a href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">Chrome extension</a>
to create aliases in one click (like in the below gif 👇).
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
This alias is automatically created for receiving SimpleLogin news and tips. <img src="https://simplelogin.io/images/one-click-alias.gif"
<br /> style="max-width: 80%;
In the next coming days, we'll send you 3 emails to help you get the best out of SimpleLogin. margin: auto;
<br /> border: 1px solid">
Please {% endcall %}
<a href="{{ URL + '/dashboard/setting#notification' }}">disable</a>
it if you don't need this.
{% endcall %}
{% endif %}
{% call text() %}
If you are using Firefox or a Chromium-browser like Chrome, Edge, Brave, you can
install our
<a href="https://addons.mozilla.org/firefox/addon/simplelogin/">Firefox add-on</a>
or
<a href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">Chrome extension</a>
to create aliases in one click (like in the below gif 👇).
{% endcall %}
{% call text() %}
<img src="https://simplelogin.io/images/one-click-alias.gif"
style="max-width: 80%; margin: auto; border: 1px solid">
{% endcall %}
{% call text() %}
SimpleLogin is also available on
<a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Android</a>
and
<a href="https://apps.apple.com/app/id1494359858">iOS</a>
so you can manage your aliases on the go.
{% endcall %}
{% if user.in_trial() and user.trial_end %}
{% call text() %} {% call text() %}
When you signed up, you can use all premium features like SimpleLogin is also available on
<em>custom domain</em>, <em>alias directory</em>, <a href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Android</a>
<em>mailbox</em>, and
<em>PGP</em> without any limit during 7 days (the "trial period"). <a href="https://apps.apple.com/app/id1494359858">iOS</a>
Everything you create during this period will so you can manage your aliases on the go.
continue to work normally even if you don't upgrade. {% endcall %}
<br />
{% endcall %}
{% call text() %} {% if user.in_trial() and user.trial_end %}
Please note that you can't create more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases during the trial period.
<br />
{% endcall %}
{% endif %} {% call text() %}
{% call text() %} When you signed up, you can use all premium features like
For any question or if you want to request a feature, <em>custom domain</em>, <em>alias directory</em>,
please submit it on our <a href="https://github.com/simple-login/app/discussions">forum</a>. <em>mailbox</em>,
You can also join our <em>PGP</em> without any limit during 7 days (the "trial period").
<a href="https://www.reddit.com/r/Simplelogin/">Reddit</a> Everything you create during this period will
or follow our continue to work normally even if you don't upgrade.
<a href="https://twitter.com/simplelogin">Twitter</a> <br />
. {% endcall %}
{% endcall %}
{% call text() %}
Please note that you can't create more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases during the trial period.
<br />
{% endcall %}
{% endif %}
{% call text() %}
For any question or if you want to request a feature,
please submit it on our <a href="https://github.com/simple-login/app/discussions">forum</a>.
You can also join our
<a href="https://www.reddit.com/r/Simplelogin/">Reddit</a>
or follow our
<a href="https://twitter.com/simplelogin">Twitter</a>
.
{% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,14 +3,14 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Your SimpleLogin account has been deleted successfully.</h1> <h1>Your SimpleLogin account has been deleted successfully.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Thank you for having used SimpleLogin. Thank you for having used SimpleLogin.
{% endcall %} {% endcall %}
{{ render_text('Best, {{ render_text('Best,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -7,7 +7,7 @@
{{ render_text("If it wasn't you, maybe someone entered your email by mistake. In this case you can ignore this mail.") }} {{ render_text("If it wasn't you, maybe someone entered your email by mistake. In this case you can ignore this mail.") }}
{{ render_button("Verify email", activation_link) }} {{ render_button("Verify email", activation_link) }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(activation_link) }} {{ raw_url(activation_link) }}
{% endblock %} {% endblock %}

View file

@ -3,17 +3,17 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>{{ alias.email }} has been transferred.</h1> <h1>{{ alias.email }} has been transferred.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Your (previously) alias {{ alias.email }} has been received by another user. Your (previously) alias {{ alias.email }} has been received by another user.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,22 +3,22 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>{{ alias.email }} is disabled</h1> <h1>{{ alias.email }} is disabled</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
There are several emails sent to your alias {{ alias.email }} that have been bounced There are several emails sent to your alias {{ alias.email }} that have been bounced
by your mailbox {{ mailbox_email }}. by your mailbox {{ mailbox_email }}.
{% endcall %} {% endcall %}
{{ render_button("View the refused email", refused_email_url) }} {{ render_button("View the refused email", refused_email_url) }}
{% call text() %} {% call text() %}
As security measure, we have disabled the alias. As security measure, we have disabled the alias.
{% endcall %} {% endcall %}
{{ render_text('Please let us know if you have any question.') }} {{ render_text("Please let us know if you have any question.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(refused_email_url) }} {{ raw_url(refused_email_url) }}
{% endblock %} {% endblock %}

View file

@ -3,27 +3,27 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Email cannot be sent to {{ contact.email }} from your alias {{ alias.email }}</h1> <h1>Email cannot be sent to {{ contact.email }} from your alias {{ alias.email }}</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
This might mean {{ contact.email }} This might mean {{ contact.email }}
<ul> <ul>
<li>is not a valid email address, or</li> <li>is not a valid email address, or</li>
<li>doesn't exist, or</li> <li>doesn't exist, or</li>
<li>its mail server refuses your email</li> <li>its mail server refuses your email</li>
</ul> </ul>
{% endcall %} {% endcall %}
{{ render_button("View the original email", refused_email_url) }} {{ render_button("View the original email", refused_email_url) }}
{% call text() %} {% call text() %}
This email is automatically deleted in 7 days. This email is automatically deleted in 7 days.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,42 +3,42 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1> <h1>
An email sent to your alias {{ alias.email }} from {{ website_email }} was <b>bounced</b> by your mailbox An email sent to your alias {{ alias.email }} from {{ website_email }} was <b>bounced</b> by your mailbox
{{ mailbox_email }} {{ mailbox_email }}
</h1> </h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
This is usually because your mailbox service thinks the email is <b>spam</b>. This is usually because your mailbox service thinks the email is <b>spam</b>.
{% endcall %} {% endcall %}
{{ render_button("View the bounced email", refused_email_url) }} {{ render_button("View the bounced email", refused_email_url) }}
{{ render_text('The email is automatically deleted in 7 days.') }} {{ render_text("The email is automatically deleted in 7 days.") }}
{% call text() %} {% call text() %}
Please consider the following options: Please consider the following options:
<br />
<ol>
<li>
If the email is not spam, you can create a
<a href="https://simplelogin.io/docs/getting-started/troubleshooting/">filter</a>
to explicitly allow all emails from SimpleLogin.
<br /> <br />
</li> <ol>
<li> <li>
If this email is indeed spam, it means your alias {{ alias.email }} is now in the hands of a spammer. If the email is not spam, you can create a
You can either <a href="https://simplelogin.io/docs/getting-started/troubleshooting/">filter</a>
<a href="{{ disable_alias_link }}">disable the alias</a> to explicitly allow all emails from SimpleLogin.
or <br />
<a href="{{ block_sender_link }}">block the sender</a> </li>
if they send too many spam emails. <li>
</li> If this email is indeed spam, it means your alias {{ alias.email }} is now in the hands of a spammer.
</ol> You can either
<br /> <a href="{{ disable_alias_link }}">disable the alias</a>
Please note that the alias can be automatically disabled if too many emails sent to it are bounced. or
{% endcall %} <a href="{{ block_sender_link }}">block the sender</a>
if they send too many spam emails.
</li>
</ol>
<br />
Please note that the alias can be automatically disabled if too many emails sent to it are bounced.
{% endcall %}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,22 +3,22 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Cannot create {{ alias }} on-the-fly</h1> <h1>Cannot create {{ alias }} on-the-fly</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
An email has been sent to the alias <b>{{ alias }}</b> that would be created automatically as you own the directory <b>{{ directory }}</b> An email has been sent to the alias <b>{{ alias }}</b> that would be created automatically as you own the directory <b>{{ directory }}</b>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
As <b>on-the-fly alias creation is disabled</b> on this directory, the alias isn't created. As <b>on-the-fly alias creation is disabled</b> on this directory, the alias isn't created.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you aren't aware of this alias, that probably means someone has discovered about your directory and is abusing it. If you aren't aware of this alias, that probably means someone has discovered about your directory and is abusing it.
{% endcall %} {% endcall %}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,13 +3,13 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Cannot create alias {{ alias }} on-the-fly</h1> <h1>Cannot create alias {{ alias }} on-the-fly</h1>
{% endcall %} {% endcall %}
{{ render_text("An email has been sent to the alias <b>" + alias + "</b> that would be created automatically as you own the directory <b>" + directory + "</b>.") }} {{ render_text("An email has been sent to the alias <b>" + alias + "</b> that would be created automatically as you own the directory <b>" + directory + "</b>.") }}
{{ render_text("However you have reached the alias limit in your current plan, this creation cannot happen.") }} {{ render_text("However you have reached the alias limit in your current plan, this creation cannot happen.") }}
{{ render_text('Please upgrade to premium plan in order to use this feature.') }} {{ render_text("Please upgrade to premium plan in order to use this feature.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,13 +3,13 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Cannot create {{ alias }} on-the-fly</h1> <h1>Cannot create {{ alias }} on-the-fly</h1>
{% endcall %} {% endcall %}
{{ render_text("An email has been sent to the alias <b>" + alias + "</b> that would be created automatically as you own the domain <b>" + domain + "</b>.") }} {{ render_text("An email has been sent to the alias <b>" + alias + "</b> that would be created automatically as you own the domain <b>" + domain + "</b>.") }}
{{ render_text("However you have reached the alias limit in your current plan, this creation cannot happen.") }} {{ render_text("However you have reached the alias limit in your current plan, this creation cannot happen.") }}
{{ render_text('Please upgrade to premium plan in order to use this feature.') }} {{ render_text("Please upgrade to premium plan in order to use this feature.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -7,7 +7,7 @@
{{ render_text("Use the button below to confirm within the next 12 hours.") }} {{ render_text("Use the button below to confirm within the next 12 hours.") }}
{{ render_button("Change email", link) }} {{ render_button("Change email", link) }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(link) }} {{ raw_url(link) }}
{% endblock %} {% endblock %}

View file

@ -6,9 +6,9 @@
{{ render_text("Thank you for choosing SimpleLogin.") }} {{ render_text("Thank you for choosing SimpleLogin.") }}
{{ render_text("To get started, please activate your account by entering the following code into the application:") }} {{ render_text("To get started, please activate your account by entering the following code into the application:") }}
{{ render_text(" {{ render_text("
<h1>" + code + "</h1> <h1>" + code + "</h1>
")}} ") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,21 +3,21 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Your subscription has been extended!</h1> <h1>Your subscription has been extended!</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Your payment with cryptocurrency has been successfully processed. Your payment with cryptocurrency has been successfully processed.
<br /> <br />
Your subscription has been extended to Your subscription has been extended to
<b>{{ coinbase_subscription.end_at.format("YYYY-MM-DD") }}</b> <b>{{ coinbase_subscription.end_at.format("YYYY-MM-DD") }}</b>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Thank you a lot for your support! Thank you a lot for your support!
{% endcall %} {% endcall %}
{{ render_text('Best, {{ render_text('Best,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,21 +3,21 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Your account has been upgraded!</h1> <h1>Your account has been upgraded!</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Your payment with cryptocurrency has been successfully processed. Your payment with cryptocurrency has been successfully processed.
<br /> <br />
Your account has been upgraded to the premium plan until Your account has been upgraded to the premium plan until
<b>{{ coinbase_subscription.end_at.format("YYYY-MM-DD") }}</b> <b>{{ coinbase_subscription.end_at.format("YYYY-MM-DD") }}</b>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Thank you a lot for your support! Thank you a lot for your support!
{% endcall %} {% endcall %}
{{ render_text('Best, {{ render_text('Best,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,16 +3,16 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Your subscription is ending soon.</h1> <h1>Your subscription is ending soon.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Your subscription ends on Your subscription ends on
<b>{{ coinbase_subscription.end_at.format("YYYY-MM-DD") }}</b> <b>{{ coinbase_subscription.end_at.format("YYYY-MM-DD") }}</b>
{% endcall %} {% endcall %}
{{ render_button("Extend your subscription", extend_subscription_url) }} {{ render_button("Extend your subscription", extend_subscription_url) }}
{{ render_text('Best, {{ render_text('Best,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,24 +3,24 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1> <h1>
An email was sent to your alias <b>{{ alias.email }}</b> from its own mailbox An email was sent to your alias <b>{{ alias.email }}</b> from its own mailbox
<b>{{ from_addr }}</b>. <b>{{ from_addr }}</b>.
</h1> </h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
SimpleLogin doesn't send this email <b>back</b> to your mailbox as it would be refused or hidden anyway by your email service. SimpleLogin doesn't send this email <b>back</b> to your mailbox as it would be refused or hidden anyway by your email service.
<br /> <br />
So no worries, there's nothing you need to do :). So no worries, there's nothing you need to do :).
{% endcall %} {% endcall %}
{{ render_button("View the email", refused_email_url) }} {{ render_button("View the email", refused_email_url) }}
{% call text() %} {% call text() %}
The email is automatically deleted in 7 days. The email is automatically deleted in 7 days.
{% endcall %} {% endcall %}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,27 +3,27 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Issues with {{ mailbox.email }}.</h1> <h1>Issues with {{ mailbox.email }}.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
We have detected that your mailbox can't reliably receive emails from SimpleLogin for a consecutive period of time. We have detected that your mailbox can't reliably receive emails from SimpleLogin for a consecutive period of time.
<br /> <br />
The mailbox will be disabled in 5 days if the problem isn't solved by then. The mailbox will be disabled in 5 days if the problem isn't solved by then.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please note that a mailbox can't be a disposable or forwarding email address. Please note that a mailbox can't be a disposable or forwarding email address.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you have any question, you can reach out to us by replying to this email. If you have any question, you can reach out to us by replying to this email.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,27 +3,27 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>{{ mailbox.email }} is disabled.</h1> <h1>{{ mailbox.email }} is disabled.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
We have detected that your mailbox can't reliably receive emails from SimpleLogin for a consecutive period of time. We have detected that your mailbox can't reliably receive emails from SimpleLogin for a consecutive period of time.
<br /> <br />
The mailbox has been therefore disabled. The mailbox has been therefore disabled.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please note that a mailbox can't be a disposable or forwarding email address. Please note that a mailbox can't be a disposable or forwarding email address.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you have any question, you can reach out to us by replying to this email. If you have any question, you can reach out to us by replying to this email.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,45 +3,45 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>{{ breached_aliases|count }} of your aliases are found in data breaches.</h1> <h1>{{ breached_aliases|count }} of your aliases are found in data breaches.</h1>
{% endcall %} {% endcall %}
<ol> <ol>
{%- for alias in breached_aliases[:10] %} {%- for alias in breached_aliases[:10] %}
<li> <li>
{% call text() %} {% call text() %}
<b>{{ alias.email }}</b> was found in {{ alias.hibp_breaches|count }} data breaches. <b>{{ alias.email }}</b> was found in {{ alias.hibp_breaches|count }} data breaches.
<br /> <br />
<ul> <ul>
{% set breaches = alias.hibp_breaches|sort(attribute='date', reverse=True) %} {% set breaches = alias.hibp_breaches|sort(attribute='date', reverse=True) %}
{%- for breach in breaches[:4] %} {%- for breach in breaches[:4] %}
<li> <li>
<b>{{ breach.name }}</b> <b>{{ breach.name }}</b>
{% if breach.date %}({{ breach.date.format('YYYY-MM-DD') }}){% endif %} {% if breach.date %}({{ breach.date.format("YYYY-MM-DD") }}){% endif %}
{{ breach.description }} {{ breach.description }}
</li> </li>
{%- endfor %} {%- endfor %}
</ul> </ul>
{% if breaches|length > 4 %}And {{ breaches|length - 4 }} more data breaches...{% endif %} {% if breaches|length > 4 %}And {{ breaches|length - 4 }} more data breaches...{% endif %}
{% endcall %}
</li>
{%- endfor %}
</ol>
{% if breached_aliases|length > 10 %}
{% call text() %}
And {{ breached_aliases|length - 10 }} more aliases...
{% endcall %} {% endcall %}
</li> {% endif %}
{%- endfor %}
</ol>
{% if breached_aliases|length > 10 %}
{% call text() %} {% call text() %}
And {{ breached_aliases|length - 10 }} more aliases... For more information, check
{% endcall %} <a href='https://haveibeenpwned.com/'>HaveIBeenPwned.com</a>
.
{% endcall %}
{% endif %} {{ render_text('Best,
{% call text() %} <br />
For more information, check SimpleLogin Team.') }}
<a href='https://haveibeenpwned.com/'>HaveIBeenPwned.com</a>
.
{% endcall %}
{{ render_text('Best,
<br />
SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -7,7 +7,7 @@
{{ render_text("This request has been blocked. However, if this was <b>not</b> you, please <b>change your password immediately.</b>") }} {{ render_text("This request has been blocked. However, if this was <b>not</b> you, please <b>change your password immediately.</b>") }}
{{ render_button("Change your password", URL ~ "/dashboard/setting#change_password") }} {{ render_button("Change your password", URL ~ "/dashboard/setting#change_password") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(URL ~ "/dashboard/setting#change_password") }} {{ raw_url(URL ~ "/dashboard/setting#change_password") }}
{% endblock %} {% endblock %}

View file

@ -3,35 +3,35 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1> <h1>
Your mailbox {{ mailbox.email }} and alias {{ alias.email }} <b>cannot</b> have the same domain. Your mailbox {{ mailbox.email }} and alias {{ alias.email }} <b>cannot</b> have the same domain.
</h1> </h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
The alias domain should point to SimpleLogin servers so emails sent to it are forwarded by SimpleLogin. The alias domain should point to SimpleLogin servers so emails sent to it are forwarded by SimpleLogin.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
The mailbox domain should be your "final" email address that can receive emails from SimpleLogin The mailbox domain should be your "final" email address that can receive emails from SimpleLogin
and cannot point to SimpleLogin. and cannot point to SimpleLogin.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please either: Please either:
<br /> <br />
<ul> <ul>
<li>update the mailbox to a final email address on {{ mailbox_url }}</li> <li>update the mailbox to a final email address on {{ mailbox_url }}</li>
<li>remove {{ alias.email }} domain from your custom domains</li> <li>remove {{ alias.email }} domain from your custom domains</li>
</ul> </ul>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Feel free reply to this email if you have any question. Feel free reply to this email if you have any question.
<br /> <br />
Best, Best,
<br /> <br />
SimpleLogin team. SimpleLogin team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,17 +3,17 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1> <h1>
Your subscription will end on <b>{{ manual_sub.end_at.format("YYYY-MM-DD") }}</b> Your subscription will end on <b>{{ manual_sub.end_at.format("YYYY-MM-DD") }}</b>
</h1> </h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please <a href="https://app.simplelogin.io/dashboard/support">contact us</a> Please <a href="https://app.simplelogin.io/dashboard/support">contact us</a>
to renew your subscription. to renew your subscription.
{% endcall %} {% endcall %}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,24 +3,24 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>An email from {{ from_header }} to {{ alias.email }} is put into Quarantine</h1> <h1>An email from {{ from_header }} to {{ alias.email }} is put into Quarantine</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
An email from {{ from_header }} to {{ alias.email }} is put into Quarantine as it fails An email from {{ from_header }} to {{ alias.email }} is put into Quarantine as it fails
<a href="https://simplelogin.io/docs/getting-started/anti-phishing/">anti-phishing measure</a> <a href="https://simplelogin.io/docs/getting-started/anti-phishing/">anti-phishing measure</a>
check. check.
{% endcall %} {% endcall %}
{{ render_button("View the original email", refused_email_url) }} {{ render_button("View the original email", refused_email_url) }}
{% call text() %} {% call text() %}
This email is automatically deleted in 7 days. This email is automatically deleted in 7 days.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,38 +3,38 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
This is SimpleLogin team. This is SimpleLogin team.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
{{ provider }} has informed us about an email sent to <b>{{ email }}</b> that might have been considered as spam, {{ provider }} has informed us about an email sent to <b>{{ email }}</b> that might have been considered as spam,
either by you or by {{ provider }} spam filter. either by you or by {{ provider }} spam filter.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please note that explicitly marking a SimpleLogin's forwarded email as Spam affects SimpleLogin email delivery, Please note that explicitly marking a SimpleLogin's forwarded email as Spam affects SimpleLogin email delivery,
has a negative effect for all users and is a violation of our terms and condition. has a negative effect for all users and is a violation of our terms and condition.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If somehow {{ provider }} considers a forwarded email as Spam, it helps us if you can move the email If somehow {{ provider }} considers a forwarded email as Spam, it helps us if you can move the email
out of the Spam folder. You can also set up a filter to avoid this out of the Spam folder. You can also set up a filter to avoid this
from happening in the future using this guide at from happening in the future using this guide at
https://simplelogin.io/docs/getting-started/troubleshooting/ https://simplelogin.io/docs/getting-started/troubleshooting/
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please don't put our emails into the Spam folder. This can end up in your account being disabled on SimpleLogin. Please don't put our emails into the Spam folder. This can end up in your account being disabled on SimpleLogin.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Don't hesitate to get in touch with us if you need more information. Don't hesitate to get in touch with us if you need more information.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,35 +3,35 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
This is SimpleLogin team. This is SimpleLogin team.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
{{ provider }} has informed us about an email sent to <b>{{ user.email }}</b> that might have been marked as spam. {{ provider }} has informed us about an email sent to <b>{{ user.email }}</b> that might have been marked as spam.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please note that explicitly marking a SimpleLogin's forwarded email as Spam affects SimpleLogin email delivery, Please note that explicitly marking a SimpleLogin's forwarded email as Spam affects SimpleLogin email delivery,
has a negative effect for all users and has a negative effect for all users and
is a violation of our terms and condition. is a violation of our terms and condition.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If thats the case, please disable the alias instead if you don't want to receive the emails sent to this alias. If thats the case, please disable the alias instead if you don't want to receive the emails sent to this alias.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If SimpleLogin isnt useful for you, please know that you can simply delete your account on the Settings page. If SimpleLogin isnt useful for you, please know that you can simply delete your account on the Settings page.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Don't hesitate to get in touch with us if you need more information. Don't hesitate to get in touch with us if you need more information.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -4,27 +4,27 @@
{{ render_text("Hi") }} {{ render_text("Hi") }}
{% call text() %} {% call text() %}
Your email cannot be sent to <b>{{ contact.email }}</b> from your alias <b>{{ alias.email }}</b>. Your email cannot be sent to <b>{{ contact.email }}</b> from your alias <b>{{ alias.email }}</b>.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Can you please verify <b>{{ contact.email }}</b> is a valid address? Can you please verify <b>{{ contact.email }}</b> is a valid address?
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Usually this is because the DNS record of <b>{{ contact_domain }}</b> does not exist. Usually this is because the DNS record of <b>{{ contact_domain }}</b> does not exist.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
You can check its DNS record on any DNS checker websites, for example https://mxtoolbox.com/SuperTool.aspx You can check its DNS record on any DNS checker websites, for example https://mxtoolbox.com/SuperTool.aspx
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please let us know if you have any question. Please let us know if you have any question.
<br /> <br />
Best, Best,
<br /> <br />
SimpleLogin team. SimpleLogin team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -3,30 +3,30 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1> <h1>
An attempt to send an email from your alias <b>{{ alias.email }}</b> using <b>{{ sender }}</b> is blocked. An attempt to send an email from your alias <b>{{ alias.email }}</b> using <b>{{ sender }}</b> is blocked.
</h1> </h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
As a measure to protect against <b>email spoofing</b>, we have blocked an attempt to send an email from your alias <b>{{ alias.email }}</b> using <b>{{ sender }}</b>. As a measure to protect against <b>email spoofing</b>, we have blocked an attempt to send an email from your alias <b>{{ alias.email }}</b> using <b>{{ sender }}</b>.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please note that sending from this alias only works from alias's owning mailboxes, that are Please note that sending from this alias only works from alias's owning mailboxes, that are
{{ mailbox_emails|join(", ") }} {{ mailbox_emails|join(", ") }}
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If {{ sender }} can indeed send emails from your alias, you can add it to the allow list: If {{ sender }} can indeed send emails from your alias, you can add it to the allow list:
{% endcall %} {% endcall %}
{{ render_button("Allow " + sender, authorize_address_link) }} {{ render_button("Allow " + sender, authorize_address_link) }}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{{ raw_url(authorize_address_link) }} {{ raw_url(authorize_address_link) }}
{% endblock %} {% endblock %}

View file

@ -8,7 +8,7 @@
{{ render_text("If the button has expired, you can request a new link by following the same process as before.") }} {{ render_text("If the button has expired, you can request a new link by following the same process as before.") }}
{{ render_text("If you did not request a password reset, no further action is required.") }} {{ render_text("If you did not request a password reset, no further action is required.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(reset_password_link) }} {{ raw_url(reset_password_link) }}
{% endblock %} {% endblock %}

View file

@ -2,12 +2,12 @@
{% block content %} {% block content %}
{{ render_text('This is an automated email from SimpleLogin.') }} {{ render_text("This is an automated email from SimpleLogin.") }}
{{ render_text("We have recorded an attempt to send an email from your email <b>" + sender + "</b> to <b>" + reply_email + "</b>.") }} {{ render_text("We have recorded an attempt to send an email from your email <b>" + sender + "</b> to <b>" + reply_email + "</b>.") }}
{{ render_text(reply_email + ' is a special email address that only receives emails from its authorized user.') }} {{ render_text(reply_email + ' is a special email address that only receives emails from its authorized user.') }}
{{ render_text('This user has been also informed of this incident.') }} {{ render_text("This user has been also informed of this incident.") }}
{{ render_text('If you have any question, you can contact us by replying to this email or consult our website at ' ~ LANDING_PAGE_URL ~ '.') }} {{ render_text('If you have any question, you can contact us by replying to this email or consult our website at ' ~ LANDING_PAGE_URL ~ '.') }}
{{ render_text('Regards, {{ render_text('Regards,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,28 +3,28 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>An email sent from your alias {{ alias.email }} to {{ website_email }} is detected as spam.</h1> <h1>An email sent from your alias {{ alias.email }} to {{ website_email }} is detected as spam.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
An email sent from your alias {{ alias.email }} to {{ website_email }} is detected as spam by our Spam Detection Engine (SpamAssassin). An email sent from your alias {{ alias.email }} to {{ website_email }} is detected as spam by our Spam Detection Engine (SpamAssassin).
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
In most of the cases, the email will be refused by your contact. In most of the cases, the email will be refused by your contact.
{% endcall %} {% endcall %}
{{ render_button("View the email", refused_email_url) }} {{ render_button("View the email", refused_email_url) }}
{% call text() %} {% call text() %}
The email is automatically deleted in 7 days. The email is automatically deleted in 7 days.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please let us know if you have any question by replying to this email. Please let us know if you have any question by replying to this email.
{% endcall %} {% endcall %}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(disable_alias_link) }} {{ raw_url(disable_alias_link) }}
{% endblock %} {% endblock %}

View file

@ -3,30 +3,30 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>An email sent to your alias {{ alias.email }} from {{ website_email }} is detected as spam</h1> <h1>An email sent to your alias {{ alias.email }} from {{ website_email }} is detected as spam</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
An email sent to your alias {{ alias.email }} from {{ website_email }} is detected as spam by our Spam Detection Engine (SpamAssassin). An email sent to your alias {{ alias.email }} from {{ website_email }} is detected as spam by our Spam Detection Engine (SpamAssassin).
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
In most of the cases, the email will be refused by your email provider. In most of the cases, the email will be refused by your email provider.
{% endcall %} {% endcall %}
{{ render_button("View the email", refused_email_url) }} {{ render_button("View the email", refused_email_url) }}
{% call text() %} {% call text() %}
The email is automatically deleted in 7 days. The email is automatically deleted in 7 days.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Your alias {{ alias.email }} is probably in the hands of a spammer now. In this case, you should disable or delete the alias immediately. Your alias {{ alias.email }} is probably in the hands of a spammer now. In this case, you should disable or delete the alias immediately.
{% endcall %} {% endcall %}
{{ render_button("Disable alias", disable_alias_link) }} {{ render_button("Disable alias", disable_alias_link) }}
{{ render_text('Please let us know if you have any question by replying to this email.') }} {{ render_text("Please let us know if you have any question by replying to this email.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(disable_alias_link) }} {{ raw_url(disable_alias_link) }}
{% endblock %} {% endblock %}

View file

@ -3,41 +3,41 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1> <h1>
Attempt to send an email from your alias <b>{{ alias }}</b> from an unknown IP address Attempt to send an email from your alias <b>{{ alias }}</b> from an unknown IP address
</h1> </h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
We have recorded an attempt to send the following email from your alias <b>{{ alias }}</b> from an unknown IP We have recorded an attempt to send the following email from your alias <b>{{ alias }}</b> from an unknown IP
address address
<b>{{ ip }}</b>. <b>{{ ip }}</b>.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
- From: <b>{{ alias }}</b> - From: <b>{{ alias }}</b>
<br /> <br />
- To: <b>{{ to_email }}</b> - To: <b>{{ to_email }}</b>
<br /> <br />
- Subject: <b>{{ subject }}</b> - Subject: <b>{{ subject }}</b>
<br /> <br />
- Time: <b>{{ time.humanize() }}</b> - Time: <b>{{ time.humanize() }}</b>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
To prevent email-spoofing, SimpleLogin enforces the SPF (Sender Policy Framework). To prevent email-spoofing, SimpleLogin enforces the SPF (Sender Policy Framework).
Emails sent from an IP address that is <b>unknown</b> by your email service are refused by default. Emails sent from an IP address that is <b>unknown</b> by your email service are refused by default.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
However you can turn off this option by going to {{ mailbox_url }}. However you can turn off this option by going to {{ mailbox_url }}.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Please only turn this protection off this if you know what you're doing :). Please only turn this protection off this if you know what you're doing :).
{% endcall %} {% endcall %}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -3,21 +3,21 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1> <h1>
Unauthorized attempt to send an email to {{ contact.email }} from your alias <b>{{ alias.email }}</b> using Unauthorized attempt to send an email to {{ contact.email }} from your alias <b>{{ alias.email }}</b> using
<b>{{ sender }}</b> has been blocked. <b>{{ sender }}</b> has been blocked.
</h1> </h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
To protect against <b>email spoofing</b>, only your mailbox can send emails on behalf of your alias. To protect against <b>email spoofing</b>, only your mailbox can send emails on behalf of your alias.
SimpleLogin also refuses emails that claim to come from your mailbox but fail DMARC. SimpleLogin also refuses emails that claim to come from your mailbox but fail DMARC.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -8,24 +8,24 @@
{{ render_text("- All aliases/domains/directories you have created are <b>kept</b> and continue working normally.") }} {{ render_text("- All aliases/domains/directories you have created are <b>kept</b> and continue working normally.") }}
{{ render_text("- You cannot create new reverse aliases.") }} {{ render_text("- You cannot create new reverse aliases.") }}
{% call text() %} {% call text() %}
- You cannot create new aliases if you exceed the free plan limit, i.e. have more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases. - You cannot create new aliases if you exceed the free plan limit, i.e. have more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
- As features like <b>catch-all</b> or <b>directory</b> allow you to create aliases on-the-fly, - As features like <b>catch-all</b> or <b>directory</b> allow you to create aliases on-the-fly,
those aliases cannot be automatically created if you have more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases. those aliases cannot be automatically created if you have more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases.
{% endcall %} {% endcall %}
{{ render_text("- You cannot add new domain or directory.") }} {{ render_text("- You cannot add new domain or directory.") }}
{{ render_text('You can upgrade today to continue using all these Premium features (and much more coming).') }} {{ render_text("You can upgrade today to continue using all these Premium features (and much more coming).") }}
{{ render_button("Upgrade your account", URL ~ "/dashboard/pricing") }} {{ render_button("Upgrade your account", URL ~ "/dashboard/pricing") }}
{{ render_text('Regardless of your choice, we want to say thank you for trying SimpleLogin. We know the product {{ render_text('Regardless of your choice, we want to say thank you for trying SimpleLogin. We know the product
requires an investment of your time, and we appreciate you giving us a chance.') }} requires an investment of your time, and we appreciate you giving us a chance.') }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ render_text('P.S. If you have any questions or need any help, please don\'t hesitate to {{ render_text('P.S. If you have any questions or need any help, please don\'t hesitate to
<a href="https://app.simplelogin.io/dashboard/support">reach out</a> <a href="https://app.simplelogin.io/dashboard/support">reach out</a>
') }} ') }}
{{ raw_url(URL ~ "/dashboard/pricing") }} {{ raw_url(URL ~ "/dashboard/pricing") }}
{% endblock %} {% endblock %}

View file

@ -3,36 +3,36 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>Your trial will end {{ user.trial_end.humanize() }}</h1> <h1>Your trial will end {{ user.trial_end.humanize() }}</h1>
{% endcall %} {% endcall %}
{{ render_text("When the trial ends:") }} {{ render_text("When the trial ends:") }}
{{ render_text("- All aliases/domains/directories you have created are <b>kept</b> and continue working normally.") }} {{ render_text("- All aliases/domains/directories you have created are <b>kept</b> and continue working normally.") }}
{% call text() %} {% call text() %}
- You cannot create new aliases if you exceed the free plan limit, i.e. have more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases. - You cannot create new aliases if you exceed the free plan limit, i.e. have more than {{ MAX_NB_EMAIL_FREE_PLAN }} aliases.
{% endcall %} {% endcall %}
{{ render_text("- You cannot add new domain or directory.") }} {{ render_text("- You cannot add new domain or directory.") }}
{{ render_text("- You cannot add new mailbox.") }} {{ render_text("- You cannot add new mailbox.") }}
{{ render_text("- You cannot create new reverse aliases.") }} {{ render_text("- You cannot create new reverse aliases.") }}
{{ render_text("- If you enable PGP Encryption, forwarded emails are not encrypted anymore.") }} {{ render_text("- If you enable PGP Encryption, forwarded emails are not encrypted anymore.") }}
{{ render_text('You can upgrade today to continue using all these Premium features (and much more coming).') }} {{ render_text("You can upgrade today to continue using all these Premium features (and much more coming).") }}
{{ render_button("Upgrade your account", URL ~ "/dashboard/pricing") }} {{ render_button("Upgrade your account", URL ~ "/dashboard/pricing") }}
{{ render_text("If you're not ready to upgrade to a paying account, you have a few other options available to you:") }} {{ render_text("If you're not ready to upgrade to a paying account, you have a few other options available to you:") }}
{{ grey_section([ {{ grey_section([
"<b>Continue with the Free Plan</b> - In the free plan you are limited to " ~ MAX_NB_EMAIL_FREE_PLAN ~ " aliases but there's no cap on bandwidth or "<b>Continue with the Free Plan</b> - In the free plan you are limited to " ~ MAX_NB_EMAIL_FREE_PLAN ~ " aliases but there's no cap on bandwidth or
number of emails forwarded/sent.", number of emails forwarded/sent.",
"<b>Share feedback</b> - If SimpleLogin isn't right for you, let us know what you were looking for and we might be able to suggest some alternatives that might be a better fit.", "<b>Share feedback</b> - If SimpleLogin isn't right for you, let us know what you were looking for and we might be able to suggest some alternatives that might be a better fit.",
"<b>Export your data</b> - If SimpleLogin wasn't a good fit, you can export your data for use elsewhere. ", "<b>Export your data</b> - If SimpleLogin wasn't a good fit, you can export your data for use elsewhere. ",
"<b>Close your account</b> - You can close your account and delete your data if SimpleLogin is not useful to you." "<b>Close your account</b> - You can close your account and delete your data if SimpleLogin is not useful to you."
]) }} ]) }}
{{ render_text('Regardless of your choice, we want to say thank you for trying SimpleLogin. We know the product {{ render_text('Regardless of your choice, we want to say thank you for trying SimpleLogin. We know the product
requires an investment of your time, and we appreciate you giving us a chance.') }} requires an investment of your time, and we appreciate you giving us a chance.') }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ render_text('P.S. If you have any questions or need any help, please don\'t hesitate to {{ render_text('P.S. If you have any questions or need any help, please don\'t hesitate to
<a href="https://app.simplelogin.io/dashboard/support">reach out</a> <a href="https://app.simplelogin.io/dashboard/support">reach out</a>
') }} ') }}
{{ raw_url(URL ~ "/dashboard/pricing") }} {{ raw_url(URL ~ "/dashboard/pricing") }}
{% endblock %} {% endblock %}

View file

@ -3,22 +3,22 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>{{ alias }} has been disabled successfully.</h1> <h1>{{ alias }} has been disabled successfully.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
The alias has been disabled thanks to the "One-click unsubscribe” provided by your mailbox service. The alias has been disabled thanks to the "One-click unsubscribe” provided by your mailbox service.
<br /> <br />
When you click on this button on a forwarded email, the alias will be disabled automatically. When you click on this button on a forwarded email, the alias will be disabled automatically.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If this is a mistake, you can re-enable the alias on the dashboard. If this is a mistake, you can re-enable the alias on the dashboard.
{% endcall %} {% endcall %}
{{ render_button("Enable Alias", enable_alias_url) }} {{ render_button("Enable Alias", enable_alias_url) }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(enable_alias_url) }} {{ raw_url(enable_alias_url) }}
{% endblock %} {% endblock %}

View file

@ -3,18 +3,18 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
<h1>You have been unsubscribed from SimpleLogin newsletter.</h1> <h1>You have been unsubscribed from SimpleLogin newsletter.</h1>
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
We would love to know why do you want to unsubscribe from our communication. We would love to know why do you want to unsubscribe from our communication.
Please let us know by replying to this email. Please let us know by replying to this email.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
Best, Best,
<br /> <br />
SimpleLogin Team. SimpleLogin Team.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -5,6 +5,6 @@
{{ render_text("Hi") }} {{ render_text("Hi") }}
{{ render_text("Please find in the attached zip file a copy of your data which are stored on SimpleLogin. ") }} {{ render_text("Please find in the attached zip file a copy of your data which are stored on SimpleLogin. ") }}
{{ render_text('Best, {{ render_text('Best,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{% endblock %} {% endblock %}

View file

@ -8,7 +8,7 @@
{{ render_button("Confirm mailbox change", link) }} {{ render_button("Confirm mailbox change", link) }}
{{ render_text("This email will only be valid for the next 15 minutes.") }} {{ render_text("This email will only be valid for the next 15 minutes.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(link) }} {{ raw_url(link) }}
{% endblock %} {% endblock %}

View file

@ -13,7 +13,7 @@
{% endif %} {% endif %}
{{ render_text("This email will only be valid for the next 15 minutes.") }} {{ render_text("This email will only be valid for the next 15 minutes.") }}
{{ render_text('Thanks, {{ render_text('Thanks,
<br /> <br />
SimpleLogin Team.') }} SimpleLogin Team.') }}
{{ raw_url(link) }} {{ raw_url(link) }}
{% endblock %} {% endblock %}

View file

@ -3,15 +3,15 @@
{% block content %} {% block content %}
{% call text() %} {% call text() %}
Hello, Hello,
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
You have tried to register multiple times to {{ service }}, and this is against the terms of service of SimpleLogin. Please don't do that anymore. You have tried to register multiple times to {{ service }}, and this is against the terms of service of SimpleLogin. Please don't do that anymore.
{% endcall %} {% endcall %}
{% call text() %} {% call text() %}
If you continue registering multiple accounts to a single service we will have to disable your account. If you continue registering multiple accounts to a single service we will have to disable your account.
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}

View file

@ -1,7 +1,9 @@
<!-- ========== FOOTER ========== --> <!-- ========== FOOTER ========== -->
<footer class="gradient-half-primary-v1" <footer class="gradient-half-primary-v1"
id="footer" id="footer"
style="background-image: linear-gradient( 150deg ,#2d1582,#19a0ff); background-repeat: repeat-x; list-style: none initial; "> style="background-image: linear-gradient( 150deg ,#2d1582,#19a0ff);
background-repeat: repeat-x;
list-style: none initial">
<div class="container space-top-2 space-bottom-1 mt-7"> <div class="container space-top-2 space-bottom-1 mt-7">
<div class="row justify-content-lg-start mb-7"> <div class="row justify-content-lg-start mb-7">
<div class="col-sm-7 col-lg-6"> <div class="col-sm-7 col-lg-6">
@ -103,16 +105,12 @@
<li> <li>
<a class="list-group-item text-white footer-item " <a class="list-group-item text-white footer-item "
rel="noopener noreferrer" rel="noopener noreferrer"
href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn"> href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">Chrome Extension</a>
Chrome Extension
</a>
</li> </li>
<li> <li>
<a class="list-group-item text-white footer-item " <a class="list-group-item text-white footer-item "
rel="noopener noreferrer" rel="noopener noreferrer"
href="https://addons.mozilla.org/firefox/addon/simplelogin/"> href="https://addons.mozilla.org/firefox/addon/simplelogin/">Firefox Add-on</a>
Firefox Add-on
</a>
</li> </li>
<li> <li>
<a class="list-group-item text-white footer-item " <a class="list-group-item text-white footer-item "
@ -140,16 +138,12 @@
<li> <li>
<a class="list-group-item text-white footer-item " <a class="list-group-item text-white footer-item "
rel="noopener noreferrer" rel="noopener noreferrer"
href="https://play.google.com/store/apps/details?id=io.simplelogin.android"> href="https://play.google.com/store/apps/details?id=io.simplelogin.android">Android (Play Store)</a>
Android (Play Store)
</a>
</li> </li>
<li> <li>
<a class="list-group-item text-white footer-item " <a class="list-group-item text-white footer-item "
rel="noopener noreferrer" rel="noopener noreferrer"
href="https://f-droid.org/en/packages/io.simplelogin.android.fdroid/"> href="https://f-droid.org/en/packages/io.simplelogin.android.fdroid/">Android (F-Droid)</a>
Android (F-Droid)
</a>
</li> </li>
</ul> </ul>
</div> </div>

Some files were not shown because too many files have changed in this diff Show more