Expanded the send_gdpr_consent_request command to add support for deletion dates, email reminder interval, email sending rate limiting, and sending to a list of users.

- Legacy-Id: 15460
This commit is contained in:
Henrik Levkowetz 2018-09-16 13:52:29 +00:00
parent 75f703578c
commit 3f9dbeada8

View file

@ -2,40 +2,93 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function
import syslog
import datetime
import sys
import time
from django.conf import settings
from django.core.management.base import BaseCommand
from django.core.management.base import BaseCommand, CommandError
import debug # pyflakes:ignore
from ietf.person.models import Person
from ietf.person.models import Person, PersonEvent
from ietf.utils.mail import send_mail
def log(message):
syslog.syslog(message)
from ietf.utils.log import log
class Command(BaseCommand):
help = (u"Send GDPR consent requests to those that need it")
help = (u"""
Send GDPR consent request emails to persons who have not indicated consent
to having their personal information stored. Each send is logged as a
PersonEvent.
By default email sending happens at a rate of 1 message per second; the
rate can be adjusted with the -r option. At the start of a run, an estimate
is given of how many persons to send to, and how long the run will take.
By default, emails are not sent out if there is less than 6 days since the
previous consent request email. The interval can be adjusted with the -m
option. One effect of this is that it is possible to break of a run and
re-start it with for instance a different rate, without having duplicate
messages go out to persons that were handled in the interrupted run.
""")
def add_arguments(self, parser):
parser.add_argument('-n', '--dry-run', dest='dryrun', action='store_true', default=False,
parser.add_argument('-n', '--dry-run', action='store_true', default=False,
help="Don't send email, just list recipients")
parser.add_argument('-d', '--date', help="Date of deletion (mentioned in message)")
parser.add_argument('-m', '--minimum-interval', type=int, default=6,
help="Minimum interval between re-sending email messages, default: %(default)s days")
parser.add_argument('-r', '--rate', type=float, default=1.0,
help='Rate of sending mail, default: %(default)s/s')
parser.add_argument('user', nargs='*')
def handle(self, *args, **options):
for person in Person.objects.exclude(consent=True):
fields = ', '.join(person.needs_consent())
event_type = 'gdpr_notice_email'
# Arguments
# --date
if 'date' in options and options['date'] != None:
try:
date = datetime.datetime.strptime(options['date'], "%Y-%m-%d").date()
except ValueError as e:
raise CommandError('%s' % e)
else:
date = datetime.date.today() + datetime.timedelta(days=30)
days = (date - datetime.date.today()).days
if days <= 1:
raise CommandError('date must be more than 1 day in the future')
# --rate
delay = 1.0/options['rate']
# --minimum_interval
minimum_interval = options['minimum_interval']
latest_previous = datetime.datetime.now() - datetime.timedelta(days=minimum_interval)
# user
self.stdout.write('Querying the database for matching person records ...')
if 'user' in options and options['user']:
persons = Person.objects.filter(user__username__in=options['user'])
else:
persons = Person.objects.exclude(consent=True).exclude(personevent__time__gt=latest_previous, personevent__type=event_type)
# Report the size of the run
runtime = persons.count() * delay
self.stdout.write('Sending to %d users; estimated time a bit more than %d:%02d hours' % (persons.count(), runtime//3600, runtime%3600//60))
for person in persons:
fields = ', '.join(person.needs_consent())
if fields and person.email_set.exists():
if options['dryrun']:
if options['dry_run']:
print(("%-32s %-32s %-32s %-32s %s" % (person.email(), person.name_from_draft or '', person.name, person.ascii, fields)).encode('utf8'))
else:
to = [ e.address for e in person.email_set.filter(active=True) ]
if not to:
to = [ e.address for e in person.email_set.all() ]
self.stdout.write("Sendimg email to %s" % to)
send_mail(None, to, None,
subject='Personal Information in the IETF Datatracker',
template='utils/personal_information_notice.txt',
context={'fields': fields, 'person': person, 'settings': settings, 'date': date, }, )
context={
'date': date, 'days': days, 'fields': fields,
'person': person, 'settings': settings,
},
)
e = PersonEvent.objects.create(person=person, type='gdpr_notice_email',
desc="Sent GDPR notice email to %s with confirmation deadline %s" % (to, date))
time.sleep(delay)