diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py index 8fc8fa106..2cfb56171 100644 --- a/ietf/doc/views_charter.py +++ b/ietf/doc/views_charter.py @@ -29,7 +29,7 @@ from ietf.person.models import Person from ietf.utils.history import find_history_active_at from ietf.utils.mail import send_mail_preformatted from ietf.utils.textupload import get_cleaned_text_file_content -from ietf.group.mails import email_iesg_secretary_re_charter +from ietf.group.mails import email_admin_re_charter class ChangeStateForm(forms.Form): charter_state = forms.ModelChoiceField(State.objects.filter(used=True, type="charter"), label="Charter state", empty_label=None, required=False) @@ -141,7 +141,7 @@ def change_state(request, name, option=None): charter.save() if message or charter_state.slug == "intrev" or charter_state.slug == "extrev": - email_iesg_secretary_re_charter(request, group, "Charter state changed to %s" % charter_state.name, message) + email_admin_re_charter(request, group, "Charter state changed to %s" % charter_state.name, message,'charter_state_edit_admin_needed') # TODO - do we need a seperate set of recipients for state changes to charters vrs other kind of documents email_state_changed(request, charter, "State changed to %s." % charter_state, 'doc_state_edited') @@ -267,7 +267,7 @@ def change_title(request, name, option=None): charter.time = datetime.datetime.now() charter.save() if message: - email_iesg_secretary_re_charter(request, group, "Charter title changed to %s" % new_title, message) + email_admin_re_charter(request, group, "Charter title changed to %s" % new_title, message,'charter_state_edit_admin_needed') email_state_changed(request, charter, "Title changed to %s." % new_title,'doc_state_edited') return redirect('doc_view', name=charter.name) else: @@ -645,7 +645,7 @@ def approve(request, name): fix_charter_revision_after_approval(charter, login) - email_iesg_secretary_re_charter(request, group, "Charter state changed to %s" % new_charter_state.name, change_description) + email_admin_re_charter(request, group, "Charter state changed to %s" % new_charter_state.name, change_description,'charter_state_edit_admin_needed') # move milestones over milestones_to_delete = list(group.groupmilestone_set.filter(state__in=("active", "review"))) diff --git a/ietf/group/edit.py b/ietf/group/edit.py index 390a34495..10bf84be7 100644 --- a/ietf/group/edit.py +++ b/ietf/group/edit.py @@ -21,8 +21,7 @@ from ietf.group.utils import get_group_or_404 from ietf.ietfauth.utils import has_role from ietf.person.fields import SearchableEmailsField from ietf.person.models import Person, Email -from ietf.group.mails import ( email_iesg_secretary_re_charter, email_iesg_secretary_personnel_change, - email_interested_parties_re_changed_delegates ) +from ietf.group.mails import ( email_admin_re_charter, email_personnel_change) from ietf.utils.ordereddict import insert_after_in_ordered_dict MAX_GROUP_DELEGATES = 3 @@ -255,6 +254,7 @@ def edit(request, group_type=None, acronym=None, action="edit"): diff('list_archive', "Mailing list archive") personnel_change_text="" + changed_personnel = set() # update roles for attr, slug, title in [('ad','ad','Shepherding AD'), ('chairs', 'chair', "Chairs"), ('secretaries', 'secr', "Secretaries"), ('techadv', 'techadv', "Tech Advisors"), ('delegates', 'delegate', "Delegates")]: new = clean[attr] @@ -276,10 +276,10 @@ def edit(request, group_type=None, acronym=None, action="edit"): if deleted: change_text=title + ' deleted: ' + ", ".join(x.formatted_email() for x in deleted) personnel_change_text+=change_text+"\n" - email_interested_parties_re_changed_delegates(request, group, title, added, deleted) + changed_personnel.update(set(old)^set(new)) if personnel_change_text!="": - email_iesg_secretary_personnel_change(request, group, personnel_change_text) + email_personnel_change(request, group, personnel_change_text, changed_personnel) # update urls new_urls = clean['urls'] @@ -357,7 +357,7 @@ def conclude(request, acronym, group_type=None): if form.is_valid(): instructions = form.cleaned_data['instructions'] - email_iesg_secretary_re_charter(request, group, "Request closing of group", instructions) + email_admin_re_charter(request, group, "Request closing of group", instructions, 'group_closure_requested') e = GroupEvent(group=group, by=request.user.person) e.type = "requested_close" diff --git a/ietf/group/mails.py b/ietf/group/mails.py index 0f4c1654e..28650e38d 100644 --- a/ietf/group/mails.py +++ b/ietf/group/mails.py @@ -14,8 +14,8 @@ from ietf.group.models import Group from ietf.group.utils import milestone_reviewer_for_group_type from ietf.mailtoken.utils import gather_address_list -def email_iesg_secretary_re_charter(request, group, subject, text): - to = gather_address_list('charter_state_message_provided',group=group) +def email_admin_re_charter(request, group, subject, text, mailtoken): + to = gather_address_list(mailtoken,group=group) full_subject = u"Regarding %s %s: %s" % (group.type.name, group.acronym, subject) text = strip_tags(text) @@ -28,42 +28,11 @@ def email_iesg_secretary_re_charter(request, group, subject, text): ) ) -def email_iesg_secretary_personnel_change(request, group, text): - to = ["iesg-secretary@ietf.org"] +def email_personnel_change(request, group, text, changed_personnel): + to = gather_address_list('group_personnel_change',group=group,changed_personnel=changed_personnel) full_subject = u"Personnel change for %s working group" % (group.acronym) send_mail_text(request, to, None, full_subject,text) -def email_interested_parties_re_changed_delegates(request, group, title, added, deleted): - - # Send to management and chairs - to = [] - if group.ad_role(): - to.append(group.ad_role().email.formatted_email()) - elif group.type_id == "rg": - to.append("IRTF Chair ") - - for r in group.role_set.filter(name="chair"): - to.append(r.formatted_email()) - - # Send to the delegates who were added or deleted - for delegate in added: - to.append(delegate.formatted_email()) - - for delegate in deleted: - to.append(delegate.formatted_email()) - - personnel_change_text="" - if added: - change_text=title + ' added: ' + ", ".join(x.formatted_email() for x in added) - personnel_change_text+=change_text+"\n" - if deleted: - change_text=title + ' deleted: ' + ", ".join(x.formatted_email() for x in deleted) - personnel_change_text+=change_text+"\n" - - if to: - full_subject = u"%s changed for %s working group" % (title, group.acronym) - send_mail_text(request, to, None, full_subject,personnel_change_text) - def email_milestones_changed(request, group, changes): def wrap_up_email(to, text): @@ -94,18 +63,12 @@ def email_milestones_changed(request, group, changes): def email_milestone_review_reminder(group, grace_period=7): """Email reminders about milestones needing review to management.""" - to = [] - - if group.ad_role(): - to.append(group.ad_role().email.formatted_email()) - elif group.type_id == "rg": - to.append("IRTF Chair ") + to = gather_address_list('milestone_review_reminder',group=group) + cc = gather_address_list('milestone_review_reminder_cc',group=group) if not to: return False - cc = [r.formatted_email() for r in group.role_set.filter(name="chair")] - now = datetime.datetime.now() too_early = True @@ -139,7 +102,7 @@ def groups_with_milestones_needing_review(): return Group.objects.filter(groupmilestone__state="review").distinct() def email_milestones_due(group, early_warning_days): - to = [r.formatted_email() for r in group.role_set.filter(name="chair")] + to = gather_address_list('milestones_due_soon',group=group) today = datetime.date.today() early_warning = today + datetime.timedelta(days=early_warning_days) @@ -166,7 +129,7 @@ def groups_needing_milestones_due_reminder(early_warning_days): return Group.objects.filter(state="active", groupmilestone__due__in=[today, today + datetime.timedelta(days=early_warning_days)], groupmilestone__resolved="", groupmilestone__state="active").distinct() def email_milestones_overdue(group): - to = [r.formatted_email() for r in group.role_set.filter(name="chair")] + to = gather_address_list('milestones_overdue',group=group) today = datetime.date.today() diff --git a/ietf/mailtoken/migrations/0002_auto_20150809_1314.py b/ietf/mailtoken/migrations/0002_auto_20150809_1314.py index dd5490ba6..945ee6043 100644 --- a/ietf/mailtoken/migrations/0002_auto_20150809_1314.py +++ b/ietf/mailtoken/migrations/0002_auto_20150809_1314.py @@ -153,6 +153,10 @@ def make_recipients(apps): desc="Any ADs holding an active DISCUSS position on a given document", template=None) + rc(slug='group_changed_personnel', + desc="Any personnel who were added or deleted when a group's personnel changes", + template='{{ changed_personnel | join:", " }}') + def make_mailtokens(apps): Recipient=apps.get_model('mailtoken','Recipient') @@ -429,8 +433,12 @@ def make_mailtokens(apps): 'doc_group_responsible_directors', ]) - mt_factory(slug='charter_state_message_provided', - desc="Recipients for extra message when provided on the charter state editing form", + mt_factory(slug='charter_state_edit_admin_needed', + desc="Recipients for message to adminstrators when a charter state edit needs followon administrative action", + recipient_slugs=['iesg_secretary']) + + mt_factory(slug='group_closure_requested', + desc="Recipients for message requesting closure of a group", recipient_slugs=['iesg_secretary']) mt_factory(slug='doc_expires_soon', @@ -508,7 +516,7 @@ def make_mailtokens(apps): ]) mt_factory(slug='sub_new_version', - desc="Recipient for notification of a new version of an existing document", + desc="Recipients for notification of a new version of an existing document", recipient_slugs=['doc_notify', 'doc_ad', 'non_ietf_stream_manager', @@ -516,6 +524,33 @@ def make_mailtokens(apps): 'doc_discussing_ads', ]) + mt_factory(slug='milestone_review_reminder', + desc="Recipients for reminder message that unapproved milestone changes need review", + recipient_slugs=['group_responsible_directors', + ]) + + mt_factory(slug='milestone_review_reminder_cc', + desc="Copied on reminder message that unapproved milestone changes need review", + recipient_slugs=['group_chairs', + ]) + + mt_factory(slug='milestones_due_soon', + desc='Recipients for reminder message for milestones about to become overdue', + recipient_slugs=['group_chairs', + ]) + + mt_factory(slug='milestones_overdue', + desc='Recipients for message about milestones that are overdue', + recipient_slugs=['group_chairs', + ]) + + mt_factory(slug='group_personnel_change', + desc="Recipients for a message noting changes in a group's personnel", + recipient_slugs=['iesg_secretary', + 'group_responsible_directors', + 'group_chairs', + 'group_changed_personnel', + ]) def forward(apps, schema_editor): diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json index ec116799d..88f2dc314 100644 --- a/ietf/name/fixtures/names.json +++ b/ietf/name/fixtures/names.json @@ -4463,6 +4463,14 @@ "model": "mailtoken.recipient", "pk": "group_chairs" }, +{ + "fields": { + "template": "{{ changed_personnel | join:\", \" }}", + "desc": "Any personnel who were added or deleted when a group's personnel changes" + }, + "model": "mailtoken.recipient", + "pk": "group_changed_personnel" +}, { "fields": { "template": "{{ group.list_email }}", @@ -4796,10 +4804,10 @@ "recipients": [ "iesg_secretary" ], - "desc": "Recipients for extra message when provided on the charter state editing form" + "desc": "Recipients for message to adminstrators when a charter state edit needs followon administrative action" }, "model": "mailtoken.mailtoken", - "pk": "charter_state_message_provided" + "pk": "charter_state_edit_admin_needed" }, { "fields": { @@ -5005,6 +5013,16 @@ "model": "mailtoken.mailtoken", "pk": "group_approved_milestones_edited" }, +{ + "fields": { + "recipients": [ + "iesg_secretary" + ], + "desc": "Recipients for message requesting closure of a group" + }, + "model": "mailtoken.mailtoken", + "pk": "group_closure_requested" +}, { "fields": { "recipients": [ @@ -5016,6 +5034,19 @@ "model": "mailtoken.mailtoken", "pk": "group_milestones_edited" }, +{ + "fields": { + "recipients": [ + "group_chairs", + "group_changed_personnel", + "group_responsible_directors", + "iesg_secretary" + ], + "desc": "Recipients for a message noting changes in a group's personnel" + }, + "model": "mailtoken.mailtoken", + "pk": "group_personnel_change" +}, { "fields": { "recipients": [ @@ -5098,6 +5129,46 @@ "model": "mailtoken.mailtoken", "pk": "last_call_requested_cc" }, +{ + "fields": { + "recipients": [ + "group_chairs" + ], + "desc": "Recipients for reminder message for milestones about to become overdue" + }, + "model": "mailtoken.mailtoken", + "pk": "milestones_due_soon" +}, +{ + "fields": { + "recipients": [ + "group_chairs" + ], + "desc": "Recipients for message about milestones that are overdue" + }, + "model": "mailtoken.mailtoken", + "pk": "milestones_overdue" +}, +{ + "fields": { + "recipients": [ + "group_responsible_directors" + ], + "desc": "Recipients for reminder message that unapproved milestone changes need review" + }, + "model": "mailtoken.mailtoken", + "pk": "milestone_review_reminder" +}, +{ + "fields": { + "recipients": [ + "group_chairs" + ], + "desc": "Copied on reminder message that unapproved milestone changes need review" + }, + "model": "mailtoken.mailtoken", + "pk": "milestone_review_reminder_cc" +}, { "fields": { "recipients": [ @@ -5253,7 +5324,7 @@ "doc_notify", "rfc_editor_if_doc_in_queue" ], - "desc": "Recipient for notification of a new version of an existing document" + "desc": "Recipients for notification of a new version of an existing document" }, "model": "mailtoken.mailtoken", "pk": "sub_new_version"