def optout_confirm(request, conf): context = PatchworkRequestContext(request) email = conf.email.strip().lower() # silently ignore duplicated optouts if EmailOptout.objects.filter(email = email).count() == 0: optout = EmailOptout(email = email) optout.save() conf.deactivate() context['email'] = conf.email return render_to_response('patchwork/optout.html', context)
def optout_confirm(request, conf): email = conf.email.strip().lower() # silently ignore duplicated optouts if EmailOptout.objects.filter(email=email).count() == 0: optout = EmailOptout(email=email) optout.save() conf.deactivate() context = { 'email': conf.email, } return render(request, 'patchwork/optout.html', context)
def send_notifications(): date_limit = datetime.datetime.now() - \ datetime.timedelta(minutes = settings.NOTIFICATION_DELAY_MINUTES) # This gets funky: we want to filter out any notifications that should # be grouped with other notifications that aren't ready to go out yet. To # do that, we join back onto PatchChangeNotification (PCN -> Patch -> # Person -> Patch -> max(PCN.last_modified)), filtering out any maxima # that are with the date_limit. qs = PatchChangeNotification.objects \ .annotate(m = Max('patch__submitter__patch__patchchangenotification' '__last_modified')) \ .filter(m__lt = date_limit) groups = itertools.groupby(qs.order_by('patch__submitter'), lambda n: n.patch.submitter) errors = [] for (recipient, notifications) in groups: notifications = list(notifications) projects = set([ n.patch.project.linkname for n in notifications ]) def delete_notifications(): pks = [ n.pk for n in notifications ] PatchChangeNotification.objects.filter(pk__in = pks).delete() if EmailOptout.is_optout(recipient.email): delete_notifications() continue context = { 'site': Site.objects.get_current(), 'person': recipient, 'notifications': notifications, 'projects': projects, } subject = render_to_string( 'patchwork/patch-change-notification-subject.text', context).strip() content = render_to_string('patchwork/patch-change-notification.mail', context) message = EmailMessage(subject = subject, body = content, from_email = settings.NOTIFICATION_FROM_EMAIL, to = [recipient.email], headers = {'Precedence': 'bulk'}) try: message.send() except ex: errors.append((recipient, ex)) continue delete_notifications() return errors
class OptinTest(TestCase): def setUp(self): self.email = u'*****@*****.**' self.optout = EmailOptout(email=self.email) self.optout.save() self.conf = EmailConfirmation(type='optin', email=self.email) self.conf.save() def testOptinValidHash(self): url = reverse('confirm', kwargs={'key': self.conf.key}) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'patchwork/optin.html') self.assertContains(response, self.email) # check that there's no optout remaining self.assertEqual(EmailOptout.objects.count(), 0) # check that the confirmation is now inactive self.assertFalse(EmailConfirmation.objects.get(pk=self.conf.pk).active)
def test_notification_optout(self): """Ensure opt-out addresses don't get notifications.""" patch = create_patch(project=self.project) PatchChangeNotification(patch=patch, orig_state=patch.state).save() self._expire_notifications() EmailOptout(email=patch.submitter.email).save() errors = send_notifications() self.assertEqual(errors, []) self.assertEqual(len(mail.outbox), 0)
class OptinTest(TestCase): def setUp(self): self.email = u'*****@*****.**' self.optout = EmailOptout(email=self.email) self.optout.save() self.conf = EmailConfirmation(type='optin', email=self.email) self.conf.save() def test_valid_hash(self): response = self.client.get( reverse('confirm', kwargs={'key': self.conf.key})) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'patchwork/optin.html') self.assertContains(response, self.email) # check that there's no optout remaining self.assertEqual(EmailOptout.objects.count(), 0) # check that the confirmation is now inactive self.assertFalse(EmailConfirmation.objects.get( pk=self.conf.pk).active)
def send_notifications(): date_limit = datetime.datetime.now() - datetime.timedelta( minutes=settings.NOTIFICATION_DELAY_MINUTES) # We delay sending notifications to a user if they have other # notifications that are still in the "pending" state. To do this, # we compare the total number of patch change notifications queued # for each user against the number of "ready" notifications. qs = PatchChangeNotification.objects.all() qs2 = PatchChangeNotification.objects\ .filter(last_modified__lt=date_limit)\ .values('patch__submitter')\ .annotate(count=Count('patch__submitter')) qs2 = {elem['patch__submitter']: elem['count'] for elem in qs2} groups = itertools.groupby(qs.order_by('patch__submitter'), lambda n: n.patch.submitter) errors = [] for (recipient, notifications) in groups: notifications = list(notifications) if recipient.id not in qs2 or qs2[recipient.id] < len(notifications): continue projects = set([n.patch.project.linkname for n in notifications]) def delete_notifications(): pks = [n.pk for n in notifications] PatchChangeNotification.objects.filter(pk__in=pks).delete() if EmailOptout.is_optout(recipient.email): delete_notifications() continue context = { 'site': Site.objects.get_current(), 'notifications': notifications, 'projects': projects, } subject = render_to_string( 'patchwork/patch-change-notification-subject.text', context).strip() content = render_to_string('patchwork/patch-change-notification.mail', context) message = EmailMessage(subject=subject, body=content, from_email=settings.NOTIFICATION_FROM_EMAIL, to=[recipient.email], headers={'Precedence': 'bulk'}) try: message.send() except smtplib.SMTPException as ex: errors.append((recipient, ex)) continue delete_notifications() return errors
def testMainEmailOptinForm(self): EmailOptout(email = self.user.email).save() form_re = self._form_re(self.optin_url, self.user.email) response = self.client.get(self.url) self.assertEquals(response.status_code, 200) self.assertTrue(form_re.search(response.content) is not None)
def setUp(self): self.email = u'*****@*****.**' self.optout = EmailOptout(email = self.email) self.optout.save() self.conf = EmailConfirmation(type = 'optin', email = self.email) self.conf.save()
def setUp(self): self.url = reverse('patchwork.views.mail.optin') self.email = u'*****@*****.**' EmailOptout(email = self.email).save()
def setUp(self): super(OptoutPreexistingTest, self).setUp() EmailOptout(email = self.email).save()
def send_notifications(): date_limit = datetime.datetime.utcnow() - datetime.timedelta( minutes=settings.NOTIFICATION_DELAY_MINUTES) # We delay sending notifications to a user if they have other # notifications that are still in the "pending" state. To do this, # we compare the total number of patch change notifications queued # for each user against the number of "ready" notifications. qs = PatchChangeNotification.objects.all() qs2 = PatchChangeNotification.objects\ .filter(last_modified__lt=date_limit)\ .values('patch__submitter')\ .annotate(count=Count('patch__submitter')) qs2 = {elem['patch__submitter']: elem['count'] for elem in qs2} groups = itertools.groupby(qs.order_by('patch__submitter'), lambda n: n.patch.submitter) errors = [] for (recipient, notifications) in groups: notifications = list(notifications) if recipient.id not in qs2 or qs2[recipient.id] < len(notifications): continue projects = set([n.patch.project.linkname for n in notifications]) def delete_notifications(): pks = [n.pk for n in notifications] PatchChangeNotification.objects.filter(pk__in=pks).delete() if EmailOptout.is_optout(recipient.email): delete_notifications() continue context = { 'site': Site.objects.get_current(), 'notifications': notifications, 'projects': projects, } subject = render_to_string( 'patchwork/patch-change-notification-subject.text', context).strip() content = render_to_string('patchwork/patch-change-notification.mail', context) message = EmailMessage(subject=subject, body=content, from_email=settings.NOTIFICATION_FROM_EMAIL, to=[recipient.email], headers={'Precedence': 'bulk'}) try: message.send() except smtplib.SMTPException as ex: errors.append((recipient, ex)) continue delete_notifications() return errors
def test_primary_email_optin_form(self): EmailOptout(email=self.user.email).save() form_re = self._form_re(reverse('mail-optin'), self.user.email) response = self.client.get(reverse('user-profile')) self.assertEqual(response.status_code, 200) self.assertIsNotNone(form_re.search(response.content.decode()))
def setUp(self): EmailOptout(email=self.email).save()
def setUp(self): self.url = reverse('mail_optin') self.email = u'*****@*****.**' EmailOptout(email=self.email).save()