Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 3937 notification email #3959

Merged
merged 9 commits into from
Apr 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@
path('_administration/email/quarterly_roundup', retail.emails.quarterly_roundup, name='quarterly_roundup'),
path('_administration/email/new_work_submission', retail.emails.new_work_submission, name='new_work_submission'),
path('_administration/email/weekly_founder_recap', retail.emails.weekly_recap, name='weekly_founder_recap'),
path(
'_administration/email/weekly_unread_notifications_email',
retail.emails.unread_notification_email_weekly_roundup,
name='unread_notifications_email_weekly_roundup'
),
path('_administration/email/new_bounty_rejection', retail.emails.new_bounty_rejection, name='new_bounty_rejection'),
path(
'_administration/email/new_bounty_acceptance',
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions app/dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1785,8 +1785,7 @@ def terms(request):
'title': _('Terms of Use'),
}
return TemplateResponse(request, 'legal/terms.html', context)



def privacy(request):
return TemplateResponse(request, 'legal/privacy.html', {})

Expand Down
30 changes: 28 additions & 2 deletions app/marketing/mails.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
render_start_work_applicant_about_to_expire, render_start_work_applicant_expired, render_start_work_approved,
render_start_work_new_applicant, render_start_work_rejected, render_subscription_terminated_email,
render_successful_contribution_email, render_support_cancellation_email, render_thank_you_for_supporting_email,
render_tip_email, render_weekly_recap,
render_tip_email, render_unread_notification_email_weekly_roundup, render_weekly_recap,
)
from sendgrid.helpers.mail import Content, Email, Mail, Personalization
from sendgrid.helpers.stats import Category
Expand Down Expand Up @@ -110,7 +110,6 @@ def send_mail(from_email, _to_email, subject, body, html=False,

return response


def nth_day_email_campaign(nth, subscriber):
firstname = subscriber.email.split('@')[0]

Expand Down Expand Up @@ -686,6 +685,33 @@ def weekly_recap(to_emails=None):
finally:
translation.activate(cur_language)

def unread_notification_email_weekly_roundup(to_emails=None):
if to_emails is None:
to_emails = []

cur_language = translation.get_language()
for to_email in to_emails:
try:
setup_lang(to_email)
html, text, subject = render_unread_notification_email_weekly_roundup(to_email)
from_email = settings.PERSONAL_CONTACT_EMAIL

if not should_suppress_notification_email(to_email, 'weeklyrecap'):
send_mail(
from_email,
to_email,
subject,
text,
html,
from_name="Kevin Owocki (Gitcoin.co)",
iamonuwa marked this conversation as resolved.
Show resolved Hide resolved
categories=['marketing', func_name()],
)
else:
print('supressed')
finally:
translation.activate(cur_language)


def gdpr_update(to_emails=None):
if to_emails is None:
to_emails = []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
'''
Copyright (C) 2019 Gitcoin Core

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

'''
import time
import warnings

from django.core.management.base import BaseCommand

from marketing.mails import unread_notification_email_weekly_roundup
from marketing.models import EmailEvent, EmailSubscriber

warnings.filterwarnings("ignore", category=DeprecationWarning)


check_already_sent = False


def is_already_sent_this_week(email):
from django.utils import timezone
then = timezone.now() - timezone.timedelta(hours=12)
qs = EmailEvent.objects.filter(created_on__gt=then)
qs = qs.filter(category__contains='weekly_roundup', email__iexact=email, event='processed')
return qs.exists()


class Command(BaseCommand):

help = 'the weekly roundup emails'

def add_arguments(self, parser):
parser.add_argument(
'-live', '--live',
action='store_true',
dest='live',
default=False,
help='Actually Send the emails'
)
parser.add_argument(
'--exclude_startswith',
dest='exclude_startswith',
type=str,
default=None,
help="exclude_startswith (optional)",
)
parser.add_argument(
'--filter_startswith',
dest='filter_startswith',
type=str,
default=None,
help="filter_startswith (optional)",
)
parser.add_argument(
'--start_counter',
dest='start_counter',
type=int,
default=0,
help="start_counter (optional)",
)

def handle(self, *args, **options):

exclude_startswith = options['exclude_startswith']
filter_startswith = options['filter_startswith']
start_counter = options['start_counter']

queryset = EmailSubscriber.objects.all()
if exclude_startswith:
queryset = queryset.exclude(email__startswith=exclude_startswith)
if filter_startswith:
queryset = queryset.filter(email__startswith=filter_startswith)
queryset = queryset.order_by('email')
email_list = list(set(queryset.values_list('email', flat=True)))

print("got {} emails".format(len(email_list)))

for index, to_email in enumerate(email_list):

# skip any that are below the start counter
if index < start_counter:
continue

print("-sending {} / {}".format(index, to_email))
if options['live']:
try:
if check_already_sent and is_already_sent_this_week(to_email):
print(' -- already sent')
else:
unread_notification_email_weekly_roundup([to_email])
time.sleep(1)
except Exception as e:
print(e)
time.sleep(5)
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
"""Handle marketing commands related tests.

Copyright (C) 2018 Gitcoin Core

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
from unittest.mock import patch

from marketing.management.commands.send_unread_notification_emails_roundup import Command
from marketing.models import EmailSubscriber
from test_plus.test import TestCase


class TestSendUnreadNotificationEmailsRoundup(TestCase):
"""Define tests for roundup."""

def setUp(self):
"""Perform setup for the testcase."""
EmailSubscriber.objects.create(
email='[email protected]',
source='mysource',
newsletter=True
)
EmailSubscriber.objects.create(
email='[email protected]',
source='mysource',
newsletter=True
)
EmailSubscriber.objects.create(
email='[email protected]',
source='mysource',
newsletter=True
)
EmailSubscriber.objects.create(
email='[email protected]',
source='mysource'
)

@patch('time.sleep')
@patch('marketing.management.commands.send_unread_notification_emails_roundup.unread_notification_email_weekly_roundup')
def test_handle_no_options(self, mock_unread_notification_email_weekly_roundup, *args):
"""Test command roundup when live option is False."""
Command().handle(exclude_startswith=None, filter_startswith=None, start_counter=0, live=False)

assert mock_unread_notification_email_weekly_roundup.call_count == 0

@patch('time.sleep')
@patch('marketing.management.commands.send_unread_notification_emails_roundup.unread_notification_email_weekly_roundup')
def test_handle_with_options(self, mock_unread_notification_email_weekly_roundup, *args):
"""Test command roundup which various options."""
Command().handle(exclude_startswith='f', filter_startswith='jack', start_counter=0, live=True)

assert mock_unread_notification_email_weekly_roundup.call_count == 1

mock_unread_notification_email_weekly_roundup.assert_called_once_with(['[email protected]'])
28 changes: 28 additions & 0 deletions app/retail/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,29 @@ def render_new_bounty(to_email, bounties, old_bounties):

return response_html, response_txt

def render_unread_notification_email_weekly_roundup(to_email, from_date=date.today(), days_ago=7):
subscriber = get_or_save_email_subscriber(to_email, 'internal')
from dashboard.models import Profile
from inbox.models import Notification
profile = Profile.objects.filter(email__iexact=to_email).last()

from_date = from_date + timedelta(days=1)
to_date = from_date - timedelta(days=days_ago)

notifications = Notification.objects.filter(to_user=profile.id, is_read=False, created_on__range=[to_date, from_date]).count()

params = {
'subscriber': subscriber,
'profile': profile.handle,
'notifications': notifications,
}

subject = "Your unread notifications"

response_html = premailer_transform(render_to_string("emails/unread_notifications_roundup/unread_notification_email_weekly_roundup.html", params))
response_txt = render_to_string("emails/unread_notifications_roundup/unread_notification_email_weekly_roundup.txt", params)

return response_html, response_txt, subject

def render_weekly_recap(to_email, from_date=date.today(), days_back=7):
sub = get_or_save_email_subscriber(to_email, 'internal')
Expand Down Expand Up @@ -1050,6 +1073,11 @@ def weekly_recap(request):
return HttpResponse(response_html)


@staff_member_required
def unread_notification_email_weekly_roundup(request):
response_html, _ = render_unread_notification_email_weekly_roundup('[email protected]')
return HttpResponse(response_html)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need an extra empty line (keeping it consistent )

@staff_member_required
def new_tip(request):
from dashboard.models import Tip
Expand Down
Loading