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
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 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