From 0cdb14ecd8c4845f3fe692f9fd334f3b9f59ff21 Mon Sep 17 00:00:00 2001 From: Berra Karaman Date: Fri, 5 Jan 2024 00:11:08 +0300 Subject: [PATCH 1/6] create templates --- .../email/email_confirmation_message.html | 39 +++ .../email_confirmation_signup_message.html | 1 + .../templates/email/activate_account.html | 39 +++ .../zubhub/templates/email/badge.html | 34 +++ .../zubhub/templates/email/bookmark.html | 40 +++ .../zubhub/templates/email/comment.html | 41 +++ .../zubhub/templates/email/email_base.html | 233 ++++++++++++++++++ .../zubhub/templates/email/follower.html | 37 +++ .../templates/email/password_reset.html | 38 +++ 9 files changed, 502 insertions(+) create mode 100644 zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html create mode 100644 zubhub_backend/zubhub/templates/account/email/email_confirmation_signup_message.html create mode 100644 zubhub_backend/zubhub/templates/email/activate_account.html create mode 100644 zubhub_backend/zubhub/templates/email/badge.html create mode 100644 zubhub_backend/zubhub/templates/email/bookmark.html create mode 100644 zubhub_backend/zubhub/templates/email/comment.html create mode 100644 zubhub_backend/zubhub/templates/email/email_base.html create mode 100644 zubhub_backend/zubhub/templates/email/follower.html create mode 100644 zubhub_backend/zubhub/templates/email/password_reset.html diff --git a/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html b/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html new file mode 100644 index 000000000..31a649fc7 --- /dev/null +++ b/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html @@ -0,0 +1,39 @@ +{% extends "email/email_base.html" %} +{% load static %} +{% load default_template_tags %} + + + +{% block title %}Activate Your Account{% endblock %} + +{% block content %} +

Activate Your Account

+ +

Dear {{ user.username }}

+

Welcome to ZubHub! We're thrilled to have you on board. To get started, we just need to confirm your email address. Please click on the button below to activate your account.

+ + + Activate your account + + +
+

Please note that this link will expire in 30 minutes.

+

If you didn’t try to sign-in or create an account on ZubHub, you can safely ignore this email.

+
+{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/account/email/email_confirmation_signup_message.html b/zubhub_backend/zubhub/templates/account/email/email_confirmation_signup_message.html new file mode 100644 index 000000000..ae475a5a5 --- /dev/null +++ b/zubhub_backend/zubhub/templates/account/email/email_confirmation_signup_message.html @@ -0,0 +1 @@ +{% include "account/email/email_confirmation_message.html" %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/activate_account.html b/zubhub_backend/zubhub/templates/email/activate_account.html new file mode 100644 index 000000000..31a649fc7 --- /dev/null +++ b/zubhub_backend/zubhub/templates/email/activate_account.html @@ -0,0 +1,39 @@ +{% extends "email/email_base.html" %} +{% load static %} +{% load default_template_tags %} + + + +{% block title %}Activate Your Account{% endblock %} + +{% block content %} +

Activate Your Account

+ +

Dear {{ user.username }}

+

Welcome to ZubHub! We're thrilled to have you on board. To get started, we just need to confirm your email address. Please click on the button below to activate your account.

+ + + Activate your account + + +
+

Please note that this link will expire in 30 minutes.

+

If you didn’t try to sign-in or create an account on ZubHub, you can safely ignore this email.

+
+{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/badge.html b/zubhub_backend/zubhub/templates/email/badge.html new file mode 100644 index 000000000..7b33340e4 --- /dev/null +++ b/zubhub_backend/zubhub/templates/email/badge.html @@ -0,0 +1,34 @@ +{% extends "email/email_base.html" %} +{% load static %} + + + +{% block title %}You got a new badge!{% endblock %} + +{% block content %} +

You got a new badge!

+

Congratulations! You’ve unlocked a new achievement and earned the prestigious {{ badge.name }} badge. 🌟

+
+ Badge image +

{{ badge.name }}

+
+

{{ badge.message }} Click + + here + + to view more. +

+{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/bookmark.html b/zubhub_backend/zubhub/templates/email/bookmark.html new file mode 100644 index 000000000..72f739853 --- /dev/null +++ b/zubhub_backend/zubhub/templates/email/bookmark.html @@ -0,0 +1,40 @@ +{% extends "email/email_base.html" %} +{% load static %} + + + +{% block title %}You've been bookmarked!{% endblock %} + +{% block content %} +

You've been bookmarked!

+ +

Your post just got bookmarked. Your content is worth saving!

+ + Project Image +

{{ project.title }}

+

{{ project.description|striptags }}

+
+
+

{{ bookmarked_by }} have bookmarked your project.

+
+ +
+

Join the conversation now and engage with your audience. Click + + here + + to view more. +

+
+{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/comment.html b/zubhub_backend/zubhub/templates/email/comment.html new file mode 100644 index 000000000..a69a7d538 --- /dev/null +++ b/zubhub_backend/zubhub/templates/email/comment.html @@ -0,0 +1,41 @@ +{% extends "email/email_base.html" %} +{% load static %} + + + +{% block title %}You got a comment!{% endblock %} + +{% block content %} +

You got a comment!

+ +

Great news! Someone just left a comment on your post. 🎉

+ + Project Image +

{{ project.title }}

+

{{ project.description|striptags }}

+
+
+

{{ commented_by }} says "{{ comment }}"

+
+ +
+

Join the conversation now and engage with your audience. Click + + here + + to view comment and respond. +

+
+{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/email_base.html b/zubhub_backend/zubhub/templates/email/email_base.html new file mode 100644 index 000000000..c6ec2fc50 --- /dev/null +++ b/zubhub_backend/zubhub/templates/email/email_base.html @@ -0,0 +1,233 @@ +{% load static %} +{% load default_template_tags %} + + + + + + + + + + + + + + {% block title %}{% endblock %} + + + + + + +
 ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏
+ + +
+ +
+ + + + + +
+ + +
+ + Zubhub's Logo + +
+ + + + +
+ + pie illustration + +
+ + +
+ + + + {% block content %}{% endblock %} + + +
+ +
+ Unstructured Studio's Logo +

Creative learning for all!

+
+ +
+ + + Facebook logo + + + + + Instagram logo + + + + + X logo + + + + + Linkedin logo + + +
+ +
+ + Help + +
+ + Unsubscribe + +
+ +
+

Unstructured Studio

+

301-4 Elsinore Path, Etobicoke, ON

+

M8V 4G7, CANADA

+

© 2023 All rights reserved.

+
+ +
+ + + +
+ + + + + \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/follower.html b/zubhub_backend/zubhub/templates/email/follower.html new file mode 100644 index 000000000..da29d7502 --- /dev/null +++ b/zubhub_backend/zubhub/templates/email/follower.html @@ -0,0 +1,37 @@ +{% extends "email/email_base.html" %} +{% load static %} + + + +{% block title %}You have a new follower!{% endblock %} + +{% block content %} +

You have a new follower!

+

You just gained a new follower! You’re becoming quite the celebrity.

+ +
+ User avatar +

{{ user.username }}

+ + + View profile + +
+{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/password_reset.html b/zubhub_backend/zubhub/templates/email/password_reset.html new file mode 100644 index 000000000..82ad25e54 --- /dev/null +++ b/zubhub_backend/zubhub/templates/email/password_reset.html @@ -0,0 +1,38 @@ +{% extends "email/email_base.html" %} +{% load static %} + + + +{% block title %}Reset Your Password{% endblock %} + +{% block content %} +

Reset Your Password

+ +

Dear {{ username }}

+

You're receiving this email because you requested to change your Zubhub password. Tap the button below to reset your password.

+ + + Reset your password + + +
+

Please note that this link will expire in 30 minutes.

+

If you didn't request this email, there's nothing to worry about. You can safely ignore it.

+
+{% endblock %} \ No newline at end of file From 7b20a8173a088f96fd7ed55515023152ffa7d54e Mon Sep 17 00:00:00 2001 From: Berra Karaman Date: Fri, 5 Jan 2024 00:11:50 +0300 Subject: [PATCH 2/6] upload images --- .../zubhub/static/images/Facebook.png | Bin 0 -> 1322 bytes .../zubhub/static/images/Instagram.png | Bin 0 -> 1700 bytes .../zubhub/static/images/Linkedin.png | Bin 0 -> 894 bytes .../zubhub/static/images/Pie-Illustration.png | Bin 0 -> 6365 bytes zubhub_backend/zubhub/static/images/Twitter.png | Bin 0 -> 1326 bytes .../zubhub/static/images/ZubHub-Logo.png | Bin 0 -> 29536 bytes .../zubhub/static/images/studio-logo-dark.png | Bin 0 -> 17578 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 zubhub_backend/zubhub/static/images/Facebook.png create mode 100644 zubhub_backend/zubhub/static/images/Instagram.png create mode 100644 zubhub_backend/zubhub/static/images/Linkedin.png create mode 100644 zubhub_backend/zubhub/static/images/Pie-Illustration.png create mode 100644 zubhub_backend/zubhub/static/images/Twitter.png create mode 100644 zubhub_backend/zubhub/static/images/ZubHub-Logo.png create mode 100644 zubhub_backend/zubhub/static/images/studio-logo-dark.png diff --git a/zubhub_backend/zubhub/static/images/Facebook.png b/zubhub_backend/zubhub/static/images/Facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..adb34c5a58935c21a80de8b8df1c9cab57cf9618 GIT binary patch literal 1322 zcmV+_1=aeAP)@~0drDELIAGL9O(c600d`2O+f$vv5yPcff*ch9735MuLIqYTa5{k7xiiURoJ8MVo!@U} z$N57OOZ&9?mJAR=2qAqG~L;ATEnoD2XE@fIhGDwk; zWlQ2P8W&{Jy+K=o#MlNa6!8Pr)nqu(PpTLZ(czu2FEeaOSKJ@?lTV1>$L5XKZ~2A7opgU z`S}TD$U2}#;YQ4Ta*i5rGv`gs+NpuQey_yhvPJ$p8Yp0ZF7aeH-ylC0`SW^)17o2} zyb?-k2VkKn#p<`0I4}zqOZo* zjRlJ3Uj{T$tw(GGTIh+sVX|Lno895%YHXk<`V8t|QMMcxh#)2cJLri%xzFIR4rGO> zLm)8%TIgZGy7+{`NL#I?>8#m&3Kr$d6Fis+jX+HYb$0js)`W;x)WK zgT8g#GZaKqVN<3K2731{w+JAl3GJY3BQmIMjHpEw1RIM;Ap9&eC&+j#4fD8^upE~y0U&j=xe g5JCtcgb-4Xe>SXe8h_x+F8}}l07*qoM6N<$f@tJW1ONa4 literal 0 HcmV?d00001 diff --git a/zubhub_backend/zubhub/static/images/Instagram.png b/zubhub_backend/zubhub/static/images/Instagram.png new file mode 100644 index 0000000000000000000000000000000000000000..2e80756d5251e668abe5c8298690d0a6d545fc78 GIT binary patch literal 1700 zcmV;V23z@wP)@~0drDELIAGL9O(c600d`2O+f$vv5yPDwRs5QmI@PzmN~p$+Ml`67f5~o(!ZkknQBUlb4-b zQLa(;@uQQ6PQG^Xxs#SNz;v?eOwA0u;%1gdlHU36tg$cFibIX4XR^dM!E zG|mBta)wc^4X z&I{AYJ^%Mu}Pb{JttzB?&gkk*iQat z-eT?d;TSjL8k+Oo9XN+m9Ixs{Au8*L%b4pBV%K)l$y=sJg(=5K&SMT7?-X?j;#fJw zg&gs4#Mw^YFkSEFz_C-U-w{A>nmH&J(!ym}vc$pA4^gi>dC${xK|}A+Ikvr}rQZ+w zK>|uOkfC=&4e@dGjo=MW8%h4wkO{4uoe~*3{vqwMk)dx8K_=~xlx849Kdj~07B{5p zwQ5Q-kRiWLR z+%nI*v%@iSuHiThm*5&nE+oUr2A$F*9=hdtZqdh7-#Klla|F;^2}7JiH?(>BVe6D- z`j6~)rynE6Ii)cKp#%fHRg{sS@DIXdqCO1g(gd2Cx~ibj3E=H_n;I8@`^Ig$wZ0U4ZEb+6!R2J=?1!Z zN;i-pKE-S;JVj0ec|{pRd^FC=H!@MWfh_SU#hZMRoCea|v}UE@R5VLDo=oI6(3F>E ziQ9`T(>+L&XB~~)PJ$+iUl9+@xixi+Ms5RXR;ev^B)5TDbit^!^pNXe zSLk|==eXD11fzsF=r2W?F%39`k*?6^-f8LHQ_isvPF*_j`@Io<={Pu666n2O7i@gJ|3~k@^%n$e?PH(wb`gpGstU> zbJf=r(0hcEo^Fs#o4HBz<0FtE@#wa~lTgxPskHt#tJbmWrpTtq#kKx>w0^I3+XbhCQ z@@x7QF0qp5bmV@-OM5|nSK1Q*abr(@j3OY8egSjti!9_AOFA6W^|DhZ(ZoTT9uztj zImDW6%O76@Gyd-4*}euQ$K-DmWjuih^5&)sLv%9LtCL<#yT)}XOf~9Oa}uo=H}xQH z)&%ncxkmS3Krk%R6J8zWwoHvUDhFXM8n4MxF-+@eLj)RXFVY~&pVHGE5ip7ii>$a@ z^rT=K*PM2bcxcCnTBO4?4pb_B6CaqRP1485T?EKA`Uk$I*evSCh%gXUuCory7~SlSl3#BbwA;w3|^c7^ccgo u^%=@UjN*5GE0s#6QmIrbl}e=&nSTM&5fGZx^prwfgF}}M_)$E)e-c?47?_1UT^vIy7~kG~Sa{h%fc1fR+ka1X3sDA9 z1+4=i4J#N{Fa$G+-YA*Cw%IwvzdR-e6#(eIdhNXtGxbp z&P+iG3Z_~#-j7^mcGbJ%c<3rtt{r}*t50cFzd0wcg0*0^)e5`A4<&1)PArV^=e^gk z#DLYsk8xtK!xIq!OE9y#Z&Tg!S3zG_#wE@W_ECtQ%5~ybfHBX*HQ7OD7cMZdM{?5PuRHT1N|OUk zXxCHOw$z{b8aX_Sr7Q0p+F!Bbq|Q}$k&tSK+Ew2xZkaA)ZR<5~y&^Y3)>4qWVcWr_ z?u@4FC5<=OH=bCz?ped4>F0Jc?RTEr!rYp_EySUHr^AMgTdQ&=W!-H&`6=7l^`^{9 z=XoFIZb;@l(X>(WPs!=?)lbe&)k(;N<%DEPx@EGc;e@6FFx2KSDJ>_Cd9ix){R8ROXaC&#;pE+`m#vPOD{OMOdA@q} z#%Bc=H2bg_bg$tHqfh&8Cxzrg~8L+&t;ucLK6U8#E&xo literal 0 HcmV?d00001 diff --git a/zubhub_backend/zubhub/static/images/Pie-Illustration.png b/zubhub_backend/zubhub/static/images/Pie-Illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..1024a455b1ca15b24107eb8beed2ec8edd0f9473 GIT binary patch literal 6365 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 literal 0 HcmV?d00001 diff --git a/zubhub_backend/zubhub/static/images/Twitter.png b/zubhub_backend/zubhub/static/images/Twitter.png new file mode 100644 index 0000000000000000000000000000000000000000..31da3a1e76c00679a0734a224c4d0c3ae1dbc279 GIT binary patch literal 1326 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 z

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 a Date: Fri, 5 Jan 2024 00:13:14 +0300 Subject: [PATCH 3/6] create celery tasks --- zubhub_backend/zubhub/creators/views.py | 9 +++ zubhub_backend/zubhub/projects/views.py | 23 ++++++++ zubhub_backend/zubhub/zubhub/tasks.py | 77 +++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 zubhub_backend/zubhub/zubhub/tasks.py diff --git a/zubhub_backend/zubhub/creators/views.py b/zubhub_backend/zubhub/creators/views.py index 76c4df953..9754b3478 100644 --- a/zubhub_backend/zubhub/creators/views.py +++ b/zubhub_backend/zubhub/creators/views.py @@ -32,6 +32,7 @@ from projects.permissions import (SustainedRateThrottle, PostUserRateThrottle, GetUserRateThrottle, GetAnonRateThrottle, CustomUserRateThrottle) +from zubhub.tasks import send_follower_notification_email # from ..projects.models import Project from .models import Location, CreatorGroup, PhoneConfirmationHMAC, GroupInviteConfirmationHMAC, CreatorGroupMembership @@ -471,6 +472,14 @@ def get_object(self): Activitylog.Type.FOLLOW, f'/creators/{obj}' ) + context = { + "user": { + "username": self.request.user.username, + "avatar": self.request.user.avatar, + "pk": self.request.user.pk + } + } + send_follower_notification_email.delay(obj.email, context) self.request.user.save() return obj diff --git a/zubhub_backend/zubhub/projects/views.py b/zubhub_backend/zubhub/projects/views.py index 69ed4ce98..015398828 100644 --- a/zubhub_backend/zubhub/projects/views.py +++ b/zubhub_backend/zubhub/projects/views.py @@ -16,6 +16,7 @@ SustainedRateThrottle, PostUserRateThrottle, GetUserRateThrottle, CustomUserRateThrottle) from activitylog.models import Activitylog +from zubhub.tasks import send_comment_notification_email, send_bookmark_notification_email from .models import Project, Comment, StaffPick, Category, Tag, PublishingRule from creators.models import Creator from .utils import (ProjectSearchCriteria, project_changed, detect_mentions, @@ -410,6 +411,16 @@ def get_object(self): f'/projects/{obj.pk}' ) + context = { + "project": { + "title": obj.title, + "description": obj.description, + "pk": obj.pk, + "image": obj.images.first().image_url, + }, + "bookmarked_by": self.request.user.username, + } + send_bookmark_notification_email.delay(obj.creator.email, context) return obj else: @@ -507,6 +518,18 @@ def create(self, request, *args, **kwargs): f'/projects/{result.pk}' ) + context = { + "project": { + "title": result.title, + "description": result.description, + "pk": result.pk, + "image": result.images.first().image_url + }, + "comment": text, + "commented_by": creator_str, + } + send_comment_notification_email.delay(result.creator.email, context) + return Response(ProjectSerializer(result, context={ 'request': request }).data, diff --git a/zubhub_backend/zubhub/zubhub/tasks.py b/zubhub_backend/zubhub/zubhub/tasks.py new file mode 100644 index 000000000..46f9e47ac --- /dev/null +++ b/zubhub_backend/zubhub/zubhub/tasks.py @@ -0,0 +1,77 @@ +from celery import shared_task +from django.core.mail import EmailMessage +from django.template.loader import render_to_string +from zubhub import settings + +@shared_task(name="zubhub.tasks.send_activation_email", bind=True) +def send_activation_email(self, email_to, context): + email_content = render_to_string("email/activate_account.html", context) + mail = EmailMessage( + "Activate Your Account!", + email_content, + settings.DEFAULT_FROM_EMAIL, + [email_to] + ) + mail.content_subtype = "html" + return mail.send() + +@shared_task(name="zubhub.tasks.send_password_reset_email", bind=True) +def send_password_reset_email(self, email_to, context): + email_content = render_to_string("email/password_reset.html", context) + mail = EmailMessage( + "Reset Your Password", + email_content, + settings.DEFAULT_FROM_EMAIL, + [email_to] + ) + mail.content_subtype = "html" + return mail.send() + +@shared_task(name="zubhub.tasks.send_bookmark_notification_email", bind=True) +def send_bookmark_notification_email(self, email_to, context): + email_content = render_to_string("email/bookmark.html", context) + mail = EmailMessage( + "You've been bookmarked!", + email_content, + settings.DEFAULT_FROM_EMAIL, + [email_to] + ) + mail.content_subtype = "html" + return mail.send() + +@shared_task(name="zubhub.tasks.send_badge_notification_email", bind=True) +def send_badge_notification_email(self, email_to, context): + email_content = render_to_string("email/badge.html", context) + mail = EmailMessage( + "You got a new badge!", + email_content, + settings.DEFAULT_FROM_EMAIL, + [email_to] + ) + mail.content_subtype = "html" + return mail.send() + +@shared_task(name="zubhub.tasks.send_comment_notification_email", bind=True) +def send_comment_notification_email(self, email_to, context): + email_content = render_to_string("email/comment.html", context) + mail = EmailMessage( + "You got a comment!", + email_content, + settings.DEFAULT_FROM_EMAIL, + [email_to], + ) + mail.content_subtype = "html" + return mail.send() + + +@shared_task(name="zubhub.tasks.send_follower_notification_email", bind=True) +def send_follower_notification_email(self, email_to, context): + email_content = render_to_string("email/follower.html", context) + mail = EmailMessage( + "You have a new follower!", + email_content, + settings.DEFAULT_FROM_EMAIL, + [email_to] + ) + mail.content_subtype = "html" + return mail.send() \ No newline at end of file From be19c5a886e0136023da845bfb102d8645edd89a Mon Sep 17 00:00:00 2001 From: Berra Karaman Date: Wed, 10 Jan 2024 15:26:18 +0300 Subject: [PATCH 4/6] use password reset email template --- zubhub_backend/zubhub/creators/serializers.py | 4 ++ .../registration/password_reset_email.html | 49 ++++++++++++++----- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/zubhub_backend/zubhub/creators/serializers.py b/zubhub_backend/zubhub/creators/serializers.py index 8d58e99e7..2b554d2e7 100644 --- a/zubhub_backend/zubhub/creators/serializers.py +++ b/zubhub_backend/zubhub/creators/serializers.py @@ -302,6 +302,10 @@ def validate_email(self, value): _('No account found with this email. Verify and try again.')) return value + def get_email_options(self): + return { + 'html_email_template_name': 'registration/password_reset_email.html' + } class CreatorGroupWithMembershipsSerializer(serializers.ModelSerializer): members = CreatorGroupMembershipSerializer(many=True) diff --git a/zubhub_backend/zubhub/templates/registration/password_reset_email.html b/zubhub_backend/zubhub/templates/registration/password_reset_email.html index 4fc6fabb1..f615086d3 100644 --- a/zubhub_backend/zubhub/templates/registration/password_reset_email.html +++ b/zubhub_backend/zubhub/templates/registration/password_reset_email.html @@ -1,13 +1,40 @@ -{% load i18n %} +{% extends "email/email_base.html" %} +{% load static %} {% load default_template_tags %} -{% autoescape off %} -{%trans "You're receiving this email because you requested a password reset for your user account at " %}{% default_display_name %} -{% trans "Please go to the following page and choose a new password:" %} -{% block reset_link %} -{# {{protocol}}://{{domain}}/password-reset-confirm?uid={{uid}}&&token={{token}} #} -{% default_frontend_protocol %}://{% default_frontend_domain %}/password-reset-confirm?uid={{uid}}&&token={{token}} +{% autoescape on %} + + +{% block title %}Reset Your Password{% endblock %} + +{% block content %} +

Reset Your Password

+ +

Dear {{ user.get_username }}

+

You're receiving this email because you requested to change your Zubhub password. Tap the button below to reset your password.

+ + + Reset your password + + +
+

Please note that this link will expire in 30 minutes.

+

If you didn't request this email, there's nothing to worry about. You can safely ignore it.

+
{% endblock %} -{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }} -{% trans "Thanks for using our site!" %} -{% trans "The " %}{% default_display_name %} {% trans " Team" %} -{% endautoescape %} \ No newline at end of file +{% endautoescape %} \ No newline at end of file From d1e9ffd149b406977ed65d0878e064589c2b917f Mon Sep 17 00:00:00 2001 From: Berra Karaman Date: Wed, 10 Jan 2024 15:43:08 +0300 Subject: [PATCH 5/6] code refactor --- .../email/email_confirmation_message.html | 9 ----- .../templates/email/activate_account.html | 39 ------------------- .../zubhub/templates/email/badge.html | 12 ------ .../zubhub/templates/email/bookmark.html | 13 ------- .../zubhub/templates/email/comment.html | 14 ------- .../zubhub/templates/email/email_base.html | 5 --- .../zubhub/templates/email/follower.html | 10 ----- .../templates/email/password_reset.html | 38 ------------------ .../registration/password_reset_email.html | 8 ---- zubhub_backend/zubhub/zubhub/tasks.py | 24 ------------ 10 files changed, 172 deletions(-) delete mode 100644 zubhub_backend/zubhub/templates/email/activate_account.html delete mode 100644 zubhub_backend/zubhub/templates/email/password_reset.html diff --git a/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html b/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html index 31a649fc7..3c42cf278 100644 --- a/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html +++ b/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html @@ -2,15 +2,6 @@ {% load static %} {% load default_template_tags %} - - {% block title %}Activate Your Account{% endblock %} {% block content %} diff --git a/zubhub_backend/zubhub/templates/email/activate_account.html b/zubhub_backend/zubhub/templates/email/activate_account.html deleted file mode 100644 index 31a649fc7..000000000 --- a/zubhub_backend/zubhub/templates/email/activate_account.html +++ /dev/null @@ -1,39 +0,0 @@ -{% extends "email/email_base.html" %} -{% load static %} -{% load default_template_tags %} - - - -{% block title %}Activate Your Account{% endblock %} - -{% block content %} -

Activate Your Account

- -

Dear {{ user.username }}

-

Welcome to ZubHub! We're thrilled to have you on board. To get started, we just need to confirm your email address. Please click on the button below to activate your account.

- - - Activate your account - - -
-

Please note that this link will expire in 30 minutes.

-

If you didn’t try to sign-in or create an account on ZubHub, you can safely ignore this email.

-
-{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/email/badge.html b/zubhub_backend/zubhub/templates/email/badge.html index 7b33340e4..29ef1f5c2 100644 --- a/zubhub_backend/zubhub/templates/email/badge.html +++ b/zubhub_backend/zubhub/templates/email/badge.html @@ -1,18 +1,6 @@ {% extends "email/email_base.html" %} {% load static %} - - {% block title %}You got a new badge!{% endblock %} {% block content %} diff --git a/zubhub_backend/zubhub/templates/email/bookmark.html b/zubhub_backend/zubhub/templates/email/bookmark.html index 72f739853..c71ca0723 100644 --- a/zubhub_backend/zubhub/templates/email/bookmark.html +++ b/zubhub_backend/zubhub/templates/email/bookmark.html @@ -1,19 +1,6 @@ {% extends "email/email_base.html" %} {% load static %} - - {% block title %}You've been bookmarked!{% endblock %} {% block content %} diff --git a/zubhub_backend/zubhub/templates/email/comment.html b/zubhub_backend/zubhub/templates/email/comment.html index a69a7d538..f56e3706a 100644 --- a/zubhub_backend/zubhub/templates/email/comment.html +++ b/zubhub_backend/zubhub/templates/email/comment.html @@ -1,20 +1,6 @@ {% extends "email/email_base.html" %} {% load static %} - - {% block title %}You got a comment!{% endblock %} {% block content %} diff --git a/zubhub_backend/zubhub/templates/email/email_base.html b/zubhub_backend/zubhub/templates/email/email_base.html index c6ec2fc50..e9fafda21 100644 --- a/zubhub_backend/zubhub/templates/email/email_base.html +++ b/zubhub_backend/zubhub/templates/email/email_base.html @@ -1,11 +1,6 @@ {% load static %} {% load default_template_tags %} - - diff --git a/zubhub_backend/zubhub/templates/email/follower.html b/zubhub_backend/zubhub/templates/email/follower.html index da29d7502..80a84ca17 100644 --- a/zubhub_backend/zubhub/templates/email/follower.html +++ b/zubhub_backend/zubhub/templates/email/follower.html @@ -1,16 +1,6 @@ {% extends "email/email_base.html" %} {% load static %} - - {% block title %}You have a new follower!{% endblock %} {% block content %} diff --git a/zubhub_backend/zubhub/templates/email/password_reset.html b/zubhub_backend/zubhub/templates/email/password_reset.html deleted file mode 100644 index 82ad25e54..000000000 --- a/zubhub_backend/zubhub/templates/email/password_reset.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "email/email_base.html" %} -{% load static %} - - - -{% block title %}Reset Your Password{% endblock %} - -{% block content %} -

Reset Your Password

- -

Dear {{ username }}

-

You're receiving this email because you requested to change your Zubhub password. Tap the button below to reset your password.

- - - Reset your password - - -
-

Please note that this link will expire in 30 minutes.

-

If you didn't request this email, there's nothing to worry about. You can safely ignore it.

-
-{% endblock %} \ No newline at end of file diff --git a/zubhub_backend/zubhub/templates/registration/password_reset_email.html b/zubhub_backend/zubhub/templates/registration/password_reset_email.html index f615086d3..25357e91d 100644 --- a/zubhub_backend/zubhub/templates/registration/password_reset_email.html +++ b/zubhub_backend/zubhub/templates/registration/password_reset_email.html @@ -2,14 +2,6 @@ {% load static %} {% load default_template_tags %} {% autoescape on %} - {% block title %}Reset Your Password{% endblock %} diff --git a/zubhub_backend/zubhub/zubhub/tasks.py b/zubhub_backend/zubhub/zubhub/tasks.py index 46f9e47ac..d28471b7e 100644 --- a/zubhub_backend/zubhub/zubhub/tasks.py +++ b/zubhub_backend/zubhub/zubhub/tasks.py @@ -3,30 +3,6 @@ from django.template.loader import render_to_string from zubhub import settings -@shared_task(name="zubhub.tasks.send_activation_email", bind=True) -def send_activation_email(self, email_to, context): - email_content = render_to_string("email/activate_account.html", context) - mail = EmailMessage( - "Activate Your Account!", - email_content, - settings.DEFAULT_FROM_EMAIL, - [email_to] - ) - mail.content_subtype = "html" - return mail.send() - -@shared_task(name="zubhub.tasks.send_password_reset_email", bind=True) -def send_password_reset_email(self, email_to, context): - email_content = render_to_string("email/password_reset.html", context) - mail = EmailMessage( - "Reset Your Password", - email_content, - settings.DEFAULT_FROM_EMAIL, - [email_to] - ) - mail.content_subtype = "html" - return mail.send() - @shared_task(name="zubhub.tasks.send_bookmark_notification_email", bind=True) def send_bookmark_notification_email(self, email_to, context): email_content = render_to_string("email/bookmark.html", context) From e4444eb0c8aa212d28289706904f8d094d6d9579 Mon Sep 17 00:00:00 2001 From: Berra Karaman Date: Wed, 10 Jan 2024 15:59:06 +0300 Subject: [PATCH 6/6] fix account verification link --- .../templates/account/email/email_confirmation_message.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html b/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html index 3c42cf278..842982ab8 100644 --- a/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html +++ b/zubhub_backend/zubhub/templates/account/email/email_confirmation_message.html @@ -11,7 +11,7 @@

Activate Your Account

Welcome to ZubHub! We're thrilled to have you on board. To get started, we just need to confirm your email address. Please click on the button below to activate your account.