Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
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
Exemple #4
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 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)
Exemple #5
0
    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)
Exemple #7
0
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
Exemple #8
0
 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)
Exemple #9
0
 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()
Exemple #10
0
 def setUp(self):
     self.url = reverse('patchwork.views.mail.optin')
     self.email = u'*****@*****.**'
     EmailOptout(email = self.email).save()
Exemple #11
0
 def setUp(self):
     super(OptoutPreexistingTest, self).setUp()
     EmailOptout(email = self.email).save()
Exemple #12
0
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()
Exemple #15
0
 def setUp(self):
     self.url = reverse('mail_optin')
     self.email = u'*****@*****.**'
     EmailOptout(email=self.email).save()