From 9dd7698636a6b005418d86223054e1ebd1ddfe0d Mon Sep 17 00:00:00 2001 From: Son NK Date: Sun, 2 Feb 2020 21:49:22 +0700 Subject: [PATCH 1/8] organize emails into transactional/ and com/ --- app/email_utils.py | 40 +++++++++---------- templates/emails/{ => com}/new-app.html | 0 templates/emails/{ => com}/new-app.txt | 0 templates/emails/{ => com}/welcome.html | 0 templates/emails/{ => com}/welcome.txt | 0 .../{ => transactional}/activation.html | 0 .../emails/{ => transactional}/activation.txt | 0 .../cannot-create-alias-directory.html | 0 .../cannot-create-alias-directory.txt | 0 .../cannot-create-alias-domain.html | 0 .../cannot-create-alias-domain.txt | 0 .../{ => transactional}/change-email.html | 0 .../{ => transactional}/change-email.txt | 0 .../reply-must-use-personal-email.html | 0 .../reply-must-use-personal-email.txt | 0 .../{ => transactional}/reset-password.html | 0 .../{ => transactional}/reset-password.txt | 0 .../{ => transactional}/test-email.html | 0 .../emails/{ => transactional}/test-email.txt | 0 .../emails/{ => transactional}/trial-end.html | 0 .../emails/{ => transactional}/trial-end.txt | 0 21 files changed, 20 insertions(+), 20 deletions(-) rename templates/emails/{ => com}/new-app.html (100%) rename templates/emails/{ => com}/new-app.txt (100%) rename templates/emails/{ => com}/welcome.html (100%) rename templates/emails/{ => com}/welcome.txt (100%) rename templates/emails/{ => transactional}/activation.html (100%) rename templates/emails/{ => transactional}/activation.txt (100%) rename templates/emails/{ => transactional}/cannot-create-alias-directory.html (100%) rename templates/emails/{ => transactional}/cannot-create-alias-directory.txt (100%) rename templates/emails/{ => transactional}/cannot-create-alias-domain.html (100%) rename templates/emails/{ => transactional}/cannot-create-alias-domain.txt (100%) rename templates/emails/{ => transactional}/change-email.html (100%) rename templates/emails/{ => transactional}/change-email.txt (100%) rename templates/emails/{ => transactional}/reply-must-use-personal-email.html (100%) rename templates/emails/{ => transactional}/reply-must-use-personal-email.txt (100%) rename templates/emails/{ => transactional}/reset-password.html (100%) rename templates/emails/{ => transactional}/reset-password.txt (100%) rename templates/emails/{ => transactional}/test-email.html (100%) rename templates/emails/{ => transactional}/test-email.txt (100%) rename templates/emails/{ => transactional}/trial-end.html (100%) rename templates/emails/{ => transactional}/trial-end.txt (100%) diff --git a/app/email_utils.py b/app/email_utils.py index c6c8fcc4..0bb88150 100644 --- a/app/email_utils.py +++ b/app/email_utils.py @@ -33,8 +33,8 @@ def send_welcome_email(user): send_email( user.email, f"Welcome to SimpleLogin {user.name}", - _render("welcome.txt", name=user.name, user=user), - _render("welcome.html", name=user.name, user=user), + _render("com/welcome.txt", name=user.name, user=user), + _render("com/welcome.html", name=user.name, user=user), ) @@ -42,8 +42,8 @@ def send_trial_end_soon_email(user): send_email( user.email, f"Your trial will end soon {user.name}", - _render("trial-end.txt", name=user.name, user=user), - _render("trial-end.html", name=user.name, user=user), + _render("transactional/trial-end.txt", name=user.name, user=user), + _render("transactional/trial-end.html", name=user.name, user=user), ) @@ -52,10 +52,10 @@ def send_activation_email(email, name, activation_link): email, f"Just one more step to join SimpleLogin {name}", _render( - "activation.txt", name=name, activation_link=activation_link, email=email + "transactional/activation.txt", name=name, activation_link=activation_link, email=email ), _render( - "activation.html", name=name, activation_link=activation_link, email=email + "transactional/activation.html", name=name, activation_link=activation_link, email=email ), ) @@ -65,10 +65,10 @@ def send_reset_password_email(email, name, reset_password_link): email, f"Reset your password on SimpleLogin", _render( - "reset-password.txt", name=name, reset_password_link=reset_password_link + "transactional/reset-password.txt", name=name, reset_password_link=reset_password_link ), _render( - "reset-password.html", name=name, reset_password_link=reset_password_link + "transactional/reset-password.html", name=name, reset_password_link=reset_password_link ), ) @@ -78,14 +78,14 @@ def send_change_email(new_email, current_email, name, link): new_email, f"Confirm email update on SimpleLogin", _render( - "change-email.txt", + "transactional/change-email.txt", name=name, link=link, new_email=new_email, current_email=current_email, ), _render( - "change-email.html", + "transactional/change-email.html", name=name, link=link, new_email=new_email, @@ -98,8 +98,8 @@ def send_new_app_email(email, name): send_email( email, f"Any question/feedback for SimpleLogin {name}?", - _render("new-app.txt", name=name), - _render("new-app.html", name=name), + _render("com/new-app.txt", name=name), + _render("com/new-app.html", name=name), ) @@ -107,8 +107,8 @@ def send_test_email_alias(email, name): send_email( email, f"This email is sent to {email}", - _render("test-email.txt", name=name, alias=email), - _render("test-email.html", name=name, alias=email), + _render("transactional/test-email.txt", name=name, alias=email), + _render("transactional/test-email.html", name=name, alias=email), ) @@ -120,13 +120,13 @@ def send_cannot_create_directory_alias(user, alias, directory): user.email, f"Alias {alias} cannot be created", _render( - "cannot-create-alias-directory.txt", + "transactional/cannot-create-alias-directory.txt", name=user.name, alias=alias, directory=directory, ), _render( - "cannot-create-alias-directory.html", + "transactional/cannot-create-alias-directory.html", name=user.name, alias=alias, directory=directory, @@ -142,10 +142,10 @@ def send_cannot_create_domain_alias(user, alias, domain): user.email, f"Alias {alias} cannot be created", _render( - "cannot-create-alias-domain.txt", name=user.name, alias=alias, domain=domain + "transactional/cannot-create-alias-domain.txt", name=user.name, alias=alias, domain=domain ), _render( - "cannot-create-alias-domain.html", + "transactional/cannot-create-alias-domain.html", name=user.name, alias=alias, domain=domain, @@ -162,14 +162,14 @@ def send_reply_alias_must_use_personal_email(user, alias, sender): user.email, f"Reply from your alias {alias} only works with your personal email", _render( - "reply-must-use-personal-email.txt", + "transactional/reply-must-use-personal-email.txt", name=user.name, alias=alias, sender=sender, user_email=user.email, ), _render( - "reply-must-use-personal-email.html", + "transactional/reply-must-use-personal-email.html", name=user.name, alias=alias, sender=sender, diff --git a/templates/emails/new-app.html b/templates/emails/com/new-app.html similarity index 100% rename from templates/emails/new-app.html rename to templates/emails/com/new-app.html diff --git a/templates/emails/new-app.txt b/templates/emails/com/new-app.txt similarity index 100% rename from templates/emails/new-app.txt rename to templates/emails/com/new-app.txt diff --git a/templates/emails/welcome.html b/templates/emails/com/welcome.html similarity index 100% rename from templates/emails/welcome.html rename to templates/emails/com/welcome.html diff --git a/templates/emails/welcome.txt b/templates/emails/com/welcome.txt similarity index 100% rename from templates/emails/welcome.txt rename to templates/emails/com/welcome.txt diff --git a/templates/emails/activation.html b/templates/emails/transactional/activation.html similarity index 100% rename from templates/emails/activation.html rename to templates/emails/transactional/activation.html diff --git a/templates/emails/activation.txt b/templates/emails/transactional/activation.txt similarity index 100% rename from templates/emails/activation.txt rename to templates/emails/transactional/activation.txt diff --git a/templates/emails/cannot-create-alias-directory.html b/templates/emails/transactional/cannot-create-alias-directory.html similarity index 100% rename from templates/emails/cannot-create-alias-directory.html rename to templates/emails/transactional/cannot-create-alias-directory.html diff --git a/templates/emails/cannot-create-alias-directory.txt b/templates/emails/transactional/cannot-create-alias-directory.txt similarity index 100% rename from templates/emails/cannot-create-alias-directory.txt rename to templates/emails/transactional/cannot-create-alias-directory.txt diff --git a/templates/emails/cannot-create-alias-domain.html b/templates/emails/transactional/cannot-create-alias-domain.html similarity index 100% rename from templates/emails/cannot-create-alias-domain.html rename to templates/emails/transactional/cannot-create-alias-domain.html diff --git a/templates/emails/cannot-create-alias-domain.txt b/templates/emails/transactional/cannot-create-alias-domain.txt similarity index 100% rename from templates/emails/cannot-create-alias-domain.txt rename to templates/emails/transactional/cannot-create-alias-domain.txt diff --git a/templates/emails/change-email.html b/templates/emails/transactional/change-email.html similarity index 100% rename from templates/emails/change-email.html rename to templates/emails/transactional/change-email.html diff --git a/templates/emails/change-email.txt b/templates/emails/transactional/change-email.txt similarity index 100% rename from templates/emails/change-email.txt rename to templates/emails/transactional/change-email.txt diff --git a/templates/emails/reply-must-use-personal-email.html b/templates/emails/transactional/reply-must-use-personal-email.html similarity index 100% rename from templates/emails/reply-must-use-personal-email.html rename to templates/emails/transactional/reply-must-use-personal-email.html diff --git a/templates/emails/reply-must-use-personal-email.txt b/templates/emails/transactional/reply-must-use-personal-email.txt similarity index 100% rename from templates/emails/reply-must-use-personal-email.txt rename to templates/emails/transactional/reply-must-use-personal-email.txt diff --git a/templates/emails/reset-password.html b/templates/emails/transactional/reset-password.html similarity index 100% rename from templates/emails/reset-password.html rename to templates/emails/transactional/reset-password.html diff --git a/templates/emails/reset-password.txt b/templates/emails/transactional/reset-password.txt similarity index 100% rename from templates/emails/reset-password.txt rename to templates/emails/transactional/reset-password.txt diff --git a/templates/emails/test-email.html b/templates/emails/transactional/test-email.html similarity index 100% rename from templates/emails/test-email.html rename to templates/emails/transactional/test-email.html diff --git a/templates/emails/test-email.txt b/templates/emails/transactional/test-email.txt similarity index 100% rename from templates/emails/test-email.txt rename to templates/emails/transactional/test-email.txt diff --git a/templates/emails/trial-end.html b/templates/emails/transactional/trial-end.html similarity index 100% rename from templates/emails/trial-end.html rename to templates/emails/transactional/trial-end.html diff --git a/templates/emails/trial-end.txt b/templates/emails/transactional/trial-end.txt similarity index 100% rename from templates/emails/trial-end.txt rename to templates/emails/transactional/trial-end.txt From 55dcf9e6a26b4435a67e3c2c8cc1feb8f140c1b8 Mon Sep 17 00:00:00 2001 From: Son NK Date: Sun, 2 Feb 2020 21:49:38 +0700 Subject: [PATCH 2/8] black format --- app/email_utils.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/app/email_utils.py b/app/email_utils.py index 0bb88150..4e917b46 100644 --- a/app/email_utils.py +++ b/app/email_utils.py @@ -52,10 +52,16 @@ def send_activation_email(email, name, activation_link): email, f"Just one more step to join SimpleLogin {name}", _render( - "transactional/activation.txt", name=name, activation_link=activation_link, email=email + "transactional/activation.txt", + name=name, + activation_link=activation_link, + email=email, ), _render( - "transactional/activation.html", name=name, activation_link=activation_link, email=email + "transactional/activation.html", + name=name, + activation_link=activation_link, + email=email, ), ) @@ -65,10 +71,14 @@ def send_reset_password_email(email, name, reset_password_link): email, f"Reset your password on SimpleLogin", _render( - "transactional/reset-password.txt", name=name, reset_password_link=reset_password_link + "transactional/reset-password.txt", + name=name, + reset_password_link=reset_password_link, ), _render( - "transactional/reset-password.html", name=name, reset_password_link=reset_password_link + "transactional/reset-password.html", + name=name, + reset_password_link=reset_password_link, ), ) @@ -142,7 +152,10 @@ def send_cannot_create_domain_alias(user, alias, domain): user.email, f"Alias {alias} cannot be created", _render( - "transactional/cannot-create-alias-domain.txt", name=user.name, alias=alias, domain=domain + "transactional/cannot-create-alias-domain.txt", + name=user.name, + alias=alias, + domain=domain, ), _render( "transactional/cannot-create-alias-domain.html", From 868762bf9f4d4d0d9bce99646e7820fcb93624b3 Mon Sep 17 00:00:00 2001 From: Son NK Date: Sun, 2 Feb 2020 22:17:04 +0700 Subject: [PATCH 3/8] support --job argument in cron: stats, notify_trial_end --- cron.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/cron.py b/cron.py index cc2fae0e..49e1880c 100644 --- a/cron.py +++ b/cron.py @@ -1,3 +1,5 @@ +import argparse + import arrow from app.config import IGNORED_EMAILS, ADMIN_EMAIL @@ -16,7 +18,7 @@ from app.models import ( from server import create_app -def send_trial_end_soon(): +def notify_trial_end(): for user in User.query.filter(User.trial_end.isnot(None)).all(): if arrow.now().shift(days=3) > user.trial_end >= arrow.now().shift(days=2): LOG.d("Send trial end email to user %s", user) @@ -106,8 +108,20 @@ nb_app: {nb_app}
if __name__ == "__main__": LOG.d("Start running cronjob") + parser = argparse.ArgumentParser() + parser.add_argument( + "-j", + "--job", + help="Choose a cron job to run", + type=str, + choices=["stats", "notify_trial_end",], + ) + args = parser.parse_args() + app = create_app() with app.app_context(): - stats() - send_trial_end_soon() + if args.job == "stats": + stats() + elif args.job == "notify_trial_end": + notify_trial_end() From 1acdd1f5924cb9f28bd1aa4a709219582c610e64 Mon Sep 17 00:00:00 2001 From: Son NK Date: Sun, 2 Feb 2020 23:38:19 +0700 Subject: [PATCH 4/8] Add entries for stat and notify_trial_end in crontab --- crontab.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crontab.yml b/crontab.yml index 579277c2..373138ae 100644 --- a/crontab.yml +++ b/crontab.yml @@ -1,6 +1,12 @@ jobs: - - name: SimpleLogin cronjob - command: python /code/cron.py + - name: SimpleLogin stats + command: python /code/cron.py -j stats shell: /bin/bash schedule: "0 0 * * *" captureStderr: true + + - name: SimpleLogin Notify Trial Ends + command: python /code/cron.py -j notify_trial_end + shell: /bin/bash + schedule: "0 8 * * *" + captureStderr: true From 1c960f7c3375ee4f1a642ae1c1bca1eb310b4297 Mon Sep 17 00:00:00 2001 From: Son NK Date: Mon, 3 Feb 2020 13:00:58 +0700 Subject: [PATCH 5/8] rename _render -> render --- app/email_utils.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/app/email_utils.py b/app/email_utils.py index 4e917b46..3934d51b 100644 --- a/app/email_utils.py +++ b/app/email_utils.py @@ -20,7 +20,7 @@ from app.config import ( from app.log import LOG -def _render(template_name, **kwargs) -> str: +def render(template_name, **kwargs) -> str: templates_dir = os.path.join(ROOT_DIR, "templates", "emails") env = Environment(loader=FileSystemLoader(templates_dir)) @@ -33,8 +33,8 @@ def send_welcome_email(user): send_email( user.email, f"Welcome to SimpleLogin {user.name}", - _render("com/welcome.txt", name=user.name, user=user), - _render("com/welcome.html", name=user.name, user=user), + render("com/welcome.txt", name=user.name, user=user), + render("com/welcome.html", name=user.name, user=user), ) @@ -42,8 +42,8 @@ def send_trial_end_soon_email(user): send_email( user.email, f"Your trial will end soon {user.name}", - _render("transactional/trial-end.txt", name=user.name, user=user), - _render("transactional/trial-end.html", name=user.name, user=user), + render("transactional/trial-end.txt", name=user.name, user=user), + render("transactional/trial-end.html", name=user.name, user=user), ) @@ -51,13 +51,13 @@ def send_activation_email(email, name, activation_link): send_email( email, f"Just one more step to join SimpleLogin {name}", - _render( + render( "transactional/activation.txt", name=name, activation_link=activation_link, email=email, ), - _render( + render( "transactional/activation.html", name=name, activation_link=activation_link, @@ -70,12 +70,12 @@ def send_reset_password_email(email, name, reset_password_link): send_email( email, f"Reset your password on SimpleLogin", - _render( + render( "transactional/reset-password.txt", name=name, reset_password_link=reset_password_link, ), - _render( + render( "transactional/reset-password.html", name=name, reset_password_link=reset_password_link, @@ -87,14 +87,14 @@ def send_change_email(new_email, current_email, name, link): send_email( new_email, f"Confirm email update on SimpleLogin", - _render( + render( "transactional/change-email.txt", name=name, link=link, new_email=new_email, current_email=current_email, ), - _render( + render( "transactional/change-email.html", name=name, link=link, @@ -108,8 +108,8 @@ def send_new_app_email(email, name): send_email( email, f"Any question/feedback for SimpleLogin {name}?", - _render("com/new-app.txt", name=name), - _render("com/new-app.html", name=name), + render("com/new-app.txt", name=name), + render("com/new-app.html", name=name), ) @@ -117,8 +117,8 @@ def send_test_email_alias(email, name): send_email( email, f"This email is sent to {email}", - _render("transactional/test-email.txt", name=name, alias=email), - _render("transactional/test-email.html", name=name, alias=email), + render("transactional/test-email.txt", name=name, alias=email), + render("transactional/test-email.html", name=name, alias=email), ) @@ -129,13 +129,13 @@ def send_cannot_create_directory_alias(user, alias, directory): send_email( user.email, f"Alias {alias} cannot be created", - _render( + render( "transactional/cannot-create-alias-directory.txt", name=user.name, alias=alias, directory=directory, ), - _render( + render( "transactional/cannot-create-alias-directory.html", name=user.name, alias=alias, @@ -151,13 +151,13 @@ def send_cannot_create_domain_alias(user, alias, domain): send_email( user.email, f"Alias {alias} cannot be created", - _render( + render( "transactional/cannot-create-alias-domain.txt", name=user.name, alias=alias, domain=domain, ), - _render( + render( "transactional/cannot-create-alias-domain.html", name=user.name, alias=alias, @@ -174,14 +174,14 @@ def send_reply_alias_must_use_personal_email(user, alias, sender): send_email( user.email, f"Reply from your alias {alias} only works with your personal email", - _render( + render( "transactional/reply-must-use-personal-email.txt", name=user.name, alias=alias, sender=sender, user_email=user.email, ), - _render( + render( "transactional/reply-must-use-personal-email.html", name=user.name, alias=alias, From e86c0655ddbc512e2014887507620bf5b0942570 Mon Sep 17 00:00:00 2001 From: Son NK Date: Mon, 3 Feb 2020 13:46:47 +0700 Subject: [PATCH 6/8] add Safari extension newsletter --- templates/emails/com/safari-extension.html | 19 +++++++++++++++++++ templates/emails/com/safari-extension.txt | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 templates/emails/com/safari-extension.html create mode 100644 templates/emails/com/safari-extension.txt diff --git a/templates/emails/com/safari-extension.html b/templates/emails/com/safari-extension.html new file mode 100644 index 00000000..bbb757e5 --- /dev/null +++ b/templates/emails/com/safari-extension.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block content %} + {{ render_text("This email is sent to " + user.email + ".") }} + + {{ render_text('Unsubscribe from our emails on https://app.simplelogin.io/dashboard/setting#notification') }} + + {{ render_text("
") }} + + {{ render_text("Hi " + user.name) }} + {{ 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 AppStore.') }} + + {{ render_text('') }} + + {{ render_text("As usual, let me know if you have any question by replying to this email.") }} + +{% endblock %} + diff --git a/templates/emails/com/safari-extension.txt b/templates/emails/com/safari-extension.txt new file mode 100644 index 00000000..d3cc2ecc --- /dev/null +++ b/templates/emails/com/safari-extension.txt @@ -0,0 +1,16 @@ +This email is sent to {{ user.email }}. +Unsubscribe from our emails on https://app.simplelogin.io/dashboard/setting#notification +---------------- + +Hi {{user.name}} + +If you use Safari on a MacBook or iMac, you should check out our new Safari extension. + +It can be installed on: + +https://apps.apple.com/us/app/simplelogin/id1494051017?mt=12&fbclid=IwAR0M0nnEKgoieMkmx91TSXrtcScj7GouqRxGgXeJz2un_5ydhIKlbAI79Io + +As usual, let me know if you have any question by replying to this email. + +Best regards, +Son - SimpleLogin founder. \ No newline at end of file From 0bea79dc8636aa3a1e7e73146cebb9adb83f6e99 Mon Sep 17 00:00:00 2001 From: Son NK Date: Mon, 3 Feb 2020 13:51:43 +0700 Subject: [PATCH 7/8] add send_safari_extension_newsletter() to shell --- shell.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/shell.py b/shell.py index 49d28955..004dd802 100644 --- a/shell.py +++ b/shell.py @@ -3,10 +3,9 @@ from IPython import embed from sqlalchemy_utils import create_database, database_exists, drop_database from app.config import DB_URI -from app.email_utils import _render +from app.email_utils import send_email, render from app.models import * from server import create_app -from app import email_utils def create_db(): @@ -31,6 +30,16 @@ def reset_db(): create_db() +def send_safari_extension_newsletter(): + for user in User.query.all(): + send_email( + user.email, + "Quickly create alias with our Safari extension", + render("com/safari-extension.txt", user=user), + render("com/safari-extension.html", user=user), + ) + + app = create_app() with app.app_context(): From 6e4e737af03d4db50edd475c16538805ee7b1ec3 Mon Sep 17 00:00:00 2001 From: Son NK Date: Tue, 4 Feb 2020 14:27:12 +0700 Subject: [PATCH 8/8] add more logging --- cron.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cron.py b/cron.py index 49e1880c..dd61bbad 100644 --- a/cron.py +++ b/cron.py @@ -122,6 +122,8 @@ if __name__ == "__main__": with app.app_context(): if args.job == "stats": + LOG.d("Compute Stats") stats() elif args.job == "notify_trial_end": + LOG.d("Notify users with trial ending soon") notify_trial_end()