From c215d2af188aee86dc5b4630eaf6888a065bd54e Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Sun, 29 Dec 2019 22:20:51 +0330 Subject: [PATCH 01/12] add celery.py define send_email function --- apps/notification/celery.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 apps/notification/celery.py diff --git a/apps/notification/celery.py b/apps/notification/celery.py new file mode 100644 index 00000000..bc34ad1c --- /dev/null +++ b/apps/notification/celery.py @@ -0,0 +1,6 @@ +from celery import shared_task + + +@shared_task(name="notification") +def send_email(): + pass From 73fc9f4ff5c71511d1fb0b9b18938d236f1ca80f Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Wed, 8 Jan 2020 15:36:45 +0330 Subject: [PATCH 02/12] celery send_email task function added --- apps/notification/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notification/celery.py b/apps/notification/celery.py index bc34ad1c..fc7d2f30 100644 --- a/apps/notification/celery.py +++ b/apps/notification/celery.py @@ -3,4 +3,4 @@ @shared_task(name="notification") def send_email(): - pass + pass \ No newline at end of file From c23536ff81e684f4d89ca371ada136c1a9fc6cb4 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Wed, 8 Jan 2020 15:43:26 +0330 Subject: [PATCH 03/12] set __str__ for notification model --- apps/notification/celery.py | 2 +- apps/notification/models.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/notification/celery.py b/apps/notification/celery.py index fc7d2f30..bc34ad1c 100644 --- a/apps/notification/celery.py +++ b/apps/notification/celery.py @@ -3,4 +3,4 @@ @shared_task(name="notification") def send_email(): - pass \ No newline at end of file + pass diff --git a/apps/notification/models.py b/apps/notification/models.py index 86c5c93c..33d7e8bd 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -3,7 +3,6 @@ from django.core.mail import send_mail from django.db import models - # Create your models here. from rest_framework.validators import UniqueValidator @@ -14,15 +13,24 @@ class Notification(models.Model): text = models.TextField(max_length=200, null=False) seen = models.BooleanField(default=False, null=False) + def __str__(self): + return self.text + class Subscriber(models.Model): email = models.EmailField(null=False, unique=True) + def __str__(self): + return self.email + class EmailText(models.Model): text = models.TextField(null=False) html = models.TextField(editable=False) + def __str__(self): + return self.text + def save(self, force_insert=False, force_update=False, using=None, update_fields=None): self.html = markdown.markdown(self.text) From ae12c724a6f6c20d4647d2a068a97536597f3bf3 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Fri, 10 Jan 2020 22:18:46 +0330 Subject: [PATCH 04/12] add notification.html and txt --- .../templates/email/notification.html | 16 ++++++++++++++++ .../templates/email/notification.txt | 9 +++++++++ 2 files changed, 25 insertions(+) create mode 100644 apps/notification/templates/email/notification.html create mode 100644 apps/notification/templates/email/notification.txt diff --git a/apps/notification/templates/email/notification.html b/apps/notification/templates/email/notification.html new file mode 100644 index 00000000..3328ad3d --- /dev/null +++ b/apps/notification/templates/email/notification.html @@ -0,0 +1,16 @@ +{% load static i18n %} + +{% get_current_language_bidi as LANGUAGE_BIDI %} + + + + + + {{ subject }} + + +{% autoescape off %} + {{ context }} +{% endautoescape %} + + diff --git a/apps/notification/templates/email/notification.txt b/apps/notification/templates/email/notification.txt new file mode 100644 index 00000000..c45ea857 --- /dev/null +++ b/apps/notification/templates/email/notification.txt @@ -0,0 +1,9 @@ +{% load static i18n %} + +{% get_current_language_bidi as LANGUAGE_BIDI %} + + + +{% autoescape off %} + {{ context }} +{% endautoescape %} \ No newline at end of file From d1a840e6c21d2a472b3dfbb3518413b0604a51e2 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Fri, 10 Jan 2020 22:19:33 +0330 Subject: [PATCH 05/12] implement sending news to subscribers --- apps/notification/celery.py | 5 +++-- apps/notification/models.py | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/notification/celery.py b/apps/notification/celery.py index bc34ad1c..9f6bd020 100644 --- a/apps/notification/celery.py +++ b/apps/notification/celery.py @@ -1,6 +1,7 @@ from celery import shared_task +from django.core.mail import EmailMultiAlternatives @shared_task(name="notification") -def send_email(): - pass +def send_email(message: EmailMultiAlternatives): + message.send() diff --git a/apps/notification/models.py b/apps/notification/models.py index 33d7e8bd..6011b0dd 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -1,6 +1,8 @@ import markdown from django.contrib.auth.models import User -from django.core.mail import send_mail +from django.template.loader import render_to_string + +from apps.notification.celery import * from django.db import models # Create your models here. @@ -25,6 +27,7 @@ def __str__(self): class EmailText(models.Model): + subject = models.CharField(null=False, max_length=100) text = models.TextField(null=False) html = models.TextField(editable=False) @@ -34,3 +37,16 @@ def __str__(self): def save(self, force_insert=False, force_update=False, using=None, update_fields=None): self.html = markdown.markdown(self.text) + subscribers = Subscriber.objects.all() + + context = { + 'subject': self.subject, + 'context': self.text + } + email_html_message = render_to_string('email/notification.html', context) + email_plaintext_message = render_to_string('email/notification.txt', context) + for index in range(start=0, stop=subscribers.count() + 1, step=20): + message = EmailMultiAlternatives(subject=self.subject, from_email="datadays.sharif@gmail.com", + cc=subscribers, body=email_plaintext_message) + message.attach_alternative(email_html_message, "text/html") + send_email.apply_async(message) From bbe29fabf5dd92eecabd9c97dd0c5d454893bd44 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Fri, 10 Jan 2020 22:35:35 +0330 Subject: [PATCH 06/12] fix range args --- apps/notification/migrations/0001_initial.py | 5 +++-- .../migrations/0002_auto_20191221_1640.py | 18 ------------------ apps/notification/models.py | 2 +- 3 files changed, 4 insertions(+), 21 deletions(-) delete mode 100644 apps/notification/migrations/0002_auto_20191221_1640.py diff --git a/apps/notification/migrations/0001_initial.py b/apps/notification/migrations/0001_initial.py index e6bfce80..5960428b 100644 --- a/apps/notification/migrations/0001_initial.py +++ b/apps/notification/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2.8 on 2019-12-21 13:54 +# Generated by Django 2.2.8 on 2020-01-10 18:56 from django.conf import settings from django.db import migrations, models @@ -18,6 +18,7 @@ class Migration(migrations.Migration): name='EmailText', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('subject', models.CharField(max_length=100)), ('text', models.TextField()), ('html', models.TextField(editable=False)), ], @@ -26,7 +27,7 @@ class Migration(migrations.Migration): name='Subscriber', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('email', models.EmailField(max_length=254)), + ('email', models.EmailField(max_length=254, unique=True)), ], ), migrations.CreateModel( diff --git a/apps/notification/migrations/0002_auto_20191221_1640.py b/apps/notification/migrations/0002_auto_20191221_1640.py deleted file mode 100644 index dece19ed..00000000 --- a/apps/notification/migrations/0002_auto_20191221_1640.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.8 on 2019-12-21 16:40 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('notification', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='subscriber', - name='email', - field=models.EmailField(max_length=254, unique=True), - ), - ] diff --git a/apps/notification/models.py b/apps/notification/models.py index 6011b0dd..76ffbba0 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -45,7 +45,7 @@ def save(self, force_insert=False, force_update=False, using=None, } email_html_message = render_to_string('email/notification.html', context) email_plaintext_message = render_to_string('email/notification.txt', context) - for index in range(start=0, stop=subscribers.count() + 1, step=20): + for index in range(0, subscribers.count() + 1, 20): message = EmailMultiAlternatives(subject=self.subject, from_email="datadays.sharif@gmail.com", cc=subscribers, body=email_plaintext_message) message.attach_alternative(email_html_message, "text/html") From 97ab433c9a39ebe3f7e7f68f7b1d112d3cb64963 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Sat, 11 Jan 2020 00:20:20 +0330 Subject: [PATCH 07/12] fix send_email celery task bugs --- apps/notification/celery.py | 16 ++++++++++++++-- apps/notification/models.py | 23 ++++++++--------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/apps/notification/celery.py b/apps/notification/celery.py index 9f6bd020..abccdf03 100644 --- a/apps/notification/celery.py +++ b/apps/notification/celery.py @@ -1,7 +1,19 @@ +import string + from celery import shared_task from django.core.mail import EmailMultiAlternatives +from django.template.loader import render_to_string @shared_task(name="notification") -def send_email(message: EmailMultiAlternatives): - message.send() +def send_email(subject: string, text: string, to: list): + context = { + 'subject': subject, + 'context': text + } + email_html_message = render_to_string('email/notification.html', context) + email_plaintext_message = render_to_string('email/notification.txt', context) + msg = EmailMultiAlternatives(subject=subject, from_email="datadays.sharif@gmail.com", + cc=to, body=email_plaintext_message) + msg.attach_alternative(email_html_message, "text/html") + msg.send() diff --git a/apps/notification/models.py b/apps/notification/models.py index 76ffbba0..37feae98 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -1,12 +1,13 @@ import markdown from django.contrib.auth.models import User +from django.core.mail import EmailMultiAlternatives from django.template.loader import render_to_string -from apps.notification.celery import * from django.db import models +from apps.notification.celery import * + # Create your models here. -from rest_framework.validators import UniqueValidator class Notification(models.Model): @@ -37,16 +38,8 @@ def __str__(self): def save(self, force_insert=False, force_update=False, using=None, update_fields=None): self.html = markdown.markdown(self.text) - subscribers = Subscriber.objects.all() - - context = { - 'subject': self.subject, - 'context': self.text - } - email_html_message = render_to_string('email/notification.html', context) - email_plaintext_message = render_to_string('email/notification.txt', context) - for index in range(0, subscribers.count() + 1, 20): - message = EmailMultiAlternatives(subject=self.subject, from_email="datadays.sharif@gmail.com", - cc=subscribers, body=email_plaintext_message) - message.attach_alternative(email_html_message, "text/html") - send_email.apply_async(message) + subscribers = Subscriber.objects.all().values() + + for i in range(0, subscribers.count() + 1, 20): + send_email.apply_async( + kwargs={'subject': self.subject, 'text': self.text, 'to': list(subscribers[i:i + 20])}) From fe3fc34256d197fd02525112f384be4bb462738f Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Tue, 14 Jan 2020 19:14:14 +0330 Subject: [PATCH 08/12] set email setting --- thebackend/settings/production.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/thebackend/settings/production.py b/thebackend/settings/production.py index 21297588..dd72df1d 100644 --- a/thebackend/settings/production.py +++ b/thebackend/settings/production.py @@ -2,7 +2,6 @@ from .development import * - SECRET_KEY = 'oaeu#@$puoeuj,#$>Ueok,4IY@#$"PU.ohukAEOUO>AYU34$IPK' DEBUG = False @@ -85,7 +84,6 @@ } } - TIME_ZONE = 'Iran' STATIC_URL = '/static/' @@ -96,10 +94,9 @@ CSRF_COOKIE_HTTPONLY = True -EMAIL_BACKEND = os.getenv('EMAIL_BACKEND') -EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS') -EMAIL_HOST = os.getenv('EMAIL_HOST') -EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER') -EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD') -EMAIL_PORT = os.getenv('EMAIL_PORT') - +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_USE_TLS = 'true' +EMAIL_HOST = 'smtp.gmail.com' +EMAIL_HOST_USER = 'datadays.sharif@gmail.com' +EMAIL_HOST_PASSWORD = 'koskeshramzomikhaichikar' +EMAIL_PORT = 587 From 78267462b514bf5bfb084d9bec796df379d26bf6 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Tue, 14 Jan 2020 19:20:38 +0330 Subject: [PATCH 09/12] change email setting --- thebackend/settings/production.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/thebackend/settings/production.py b/thebackend/settings/production.py index dd72df1d..2fc33542 100644 --- a/thebackend/settings/production.py +++ b/thebackend/settings/production.py @@ -95,8 +95,8 @@ CSRF_COOKIE_HTTPONLY = True EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -EMAIL_USE_TLS = 'true' +EMAIL_USE_TLS = True EMAIL_HOST = 'smtp.gmail.com' EMAIL_HOST_USER = 'datadays.sharif@gmail.com' -EMAIL_HOST_PASSWORD = 'koskeshramzomikhaichikar' +EMAIL_HOST_PASSWORD = '' EMAIL_PORT = 587 From e29db9b29854fba1a12631054662e979e274a006 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Tue, 14 Jan 2020 19:51:53 +0330 Subject: [PATCH 10/12] implement celery task to sending email --- apps/notification/celery.py | 2 +- apps/notification/models.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/notification/celery.py b/apps/notification/celery.py index abccdf03..196709bc 100644 --- a/apps/notification/celery.py +++ b/apps/notification/celery.py @@ -14,6 +14,6 @@ def send_email(subject: string, text: string, to: list): email_html_message = render_to_string('email/notification.html', context) email_plaintext_message = render_to_string('email/notification.txt', context) msg = EmailMultiAlternatives(subject=subject, from_email="datadays.sharif@gmail.com", - cc=to, body=email_plaintext_message) + bcc=to, body=email_plaintext_message) msg.attach_alternative(email_html_message, "text/html") msg.send() diff --git a/apps/notification/models.py b/apps/notification/models.py index 37feae98..087a3e7e 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -38,8 +38,10 @@ def __str__(self): def save(self, force_insert=False, force_update=False, using=None, update_fields=None): self.html = markdown.markdown(self.text) - subscribers = Subscriber.objects.all().values() + subscribers = list() + for subscriber in Subscriber.objects.values_list('email'): + subscribers.append(subscriber[0]) + for i in range(0, len(subscribers) + 1, 20): + send_email.apply_async([self.subject, self.text, subscribers[i:i + 20]]) - for i in range(0, subscribers.count() + 1, 20): - send_email.apply_async( - kwargs={'subject': self.subject, 'text': self.text, 'to': list(subscribers[i:i + 20])}) + super().save(force_insert, force_update, using, update_fields) From 8551f411b22ee68d30660bf8c4384efc60ea1a55 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Tue, 14 Jan 2020 21:34:08 +0330 Subject: [PATCH 11/12] put a 60s delay between sending notifications emails --- apps/notification/celery.py | 2 ++ .../migrations/0002_emailtext_receivers.py | 18 ++++++++++++++++++ apps/notification/models.py | 1 + 3 files changed, 21 insertions(+) create mode 100644 apps/notification/migrations/0002_emailtext_receivers.py diff --git a/apps/notification/celery.py b/apps/notification/celery.py index 196709bc..3ca31569 100644 --- a/apps/notification/celery.py +++ b/apps/notification/celery.py @@ -1,4 +1,5 @@ import string +import time from celery import shared_task from django.core.mail import EmailMultiAlternatives @@ -17,3 +18,4 @@ def send_email(subject: string, text: string, to: list): bcc=to, body=email_plaintext_message) msg.attach_alternative(email_html_message, "text/html") msg.send() + time.sleep(60) diff --git a/apps/notification/migrations/0002_emailtext_receivers.py b/apps/notification/migrations/0002_emailtext_receivers.py new file mode 100644 index 00000000..0901c977 --- /dev/null +++ b/apps/notification/migrations/0002_emailtext_receivers.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.8 on 2020-01-14 17:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('notification', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='emailtext', + name='receivers', + field=models.ManyToManyField(to='notification.Subscriber'), + ), + ] diff --git a/apps/notification/models.py b/apps/notification/models.py index 087a3e7e..eaddc1df 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -31,6 +31,7 @@ class EmailText(models.Model): subject = models.CharField(null=False, max_length=100) text = models.TextField(null=False) html = models.TextField(editable=False) + receivers = models.ManyToManyField(Subscriber) def __str__(self): return self.text From 946805eec40b1c21ae297617dfe9492f2cc7ec89 Mon Sep 17 00:00:00 2001 From: mhbahmani Date: Wed, 15 Jan 2020 15:34:44 +0330 Subject: [PATCH 12/12] disable sending email on editing Email Text --- apps/notification/models.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/notification/models.py b/apps/notification/models.py index eaddc1df..e00a9a20 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -39,10 +39,11 @@ def __str__(self): def save(self, force_insert=False, force_update=False, using=None, update_fields=None): self.html = markdown.markdown(self.text) - subscribers = list() - for subscriber in Subscriber.objects.values_list('email'): - subscribers.append(subscriber[0]) - for i in range(0, len(subscribers) + 1, 20): - send_email.apply_async([self.subject, self.text, subscribers[i:i + 20]]) + if not self.pk: + subscribers = list() + for subscriber in Subscriber.objects.values_list('email'): + subscribers.append(subscriber[0]) + for i in range(0, len(subscribers) + 1, 20): + send_email.apply_async([self.subject, self.text, subscribers[i:i + 20]]) super().save(force_insert, force_update, using, update_fields)