diff --git a/helpdesk/settings.py b/helpdesk/settings.py index 91f60afe..30c7b1c2 100644 --- a/helpdesk/settings.py +++ b/helpdesk/settings.py @@ -357,6 +357,11 @@ HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES = getattr( False, ) +# If True, private follow-ups (public=False) will not trigger any email notifications +HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS = getattr( + settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False +) + ######################################## # options for staff.create_ticket view # ######################################## diff --git a/helpdesk/tests/test_email_notifications.py b/helpdesk/tests/test_email_notifications.py index c9d89d8a..f86df03d 100644 --- a/helpdesk/tests/test_email_notifications.py +++ b/helpdesk/tests/test_email_notifications.py @@ -407,3 +407,245 @@ class TicketEmailNotificationTests(TestCase): ticket.submitter_email in recipient_list, "Submitter email not found in email notifications sent.", ) + + def test_private_followup_default_behavior_no_submitter_emails(self): + """Test that private follow-ups normally don't send submitter emails (existing behavior).""" + # Ensure our new setting is disabled (default behavior) and HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES is False + original_setting = getattr( + helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False + ) + original_notify_all = getattr( + helpdesk_settings, "HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES", False + ) + setattr(helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False) + setattr( + helpdesk_settings, "HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES", False + ) + + try: + self.outbox.clear() # Clear any existing emails + update_ticket( + user=self.update_user, + ticket=self.existing_ticket, + comment="This is a private comment", + public=False, # Private followup + ) + + email_cnt = len(self.outbox) + # Private follow-ups don't send submitter emails by default (only to assigned users if they have email notifications enabled) + # Since our test ticket is unassigned, no emails should be sent + self.assertEqual( + email_cnt, + 0, + f"Expected 0 email notifications for private followup (existing behavior). {email_cnt} were sent.", + ) + finally: + # Restore original settings + setattr( + helpdesk_settings, + "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", + original_setting, + ) + setattr( + helpdesk_settings, + "HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES", + original_notify_all, + ) + + def test_private_followup_no_emails_setting_enabled(self): + """Test that private follow-ups don't send emails when HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS is True.""" + # Enable the setting + original_setting = getattr( + helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False + ) + setattr(helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", True) + + try: + self.outbox.clear() # Clear any existing emails + update_ticket( + user=self.update_user, + ticket=self.existing_ticket, + comment="This is a private comment", + public=False, # Private followup + ) + + email_cnt = len(self.outbox) + self.assertEqual( + email_cnt, + 0, + f"Expected 0 email notifications for private followup when setting is enabled. {email_cnt} were sent.", + ) + finally: + # Restore original setting + setattr( + helpdesk_settings, + "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", + original_setting, + ) + + def test_private_followup_setting_does_not_affect_public_followups(self): + """Test that public follow-ups still send emails when HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS is True.""" + # Enable the setting + original_setting = getattr( + helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False + ) + setattr(helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", True) + + try: + self.outbox.clear() # Clear any existing emails + update_ticket( + user=self.update_user, + ticket=self.existing_ticket, + comment="This is a public comment", + public=True, # Public followup + ) + + email_cnt = len(self.outbox) + self.assertGreater( + email_cnt, + 0, + "Expected email notifications for public followup even when private followup setting is enabled.", + ) + + # Verify submitter received email + recipient_list = [email.to[0] for email in self.outbox] + self.assertIn( + self.existing_ticket.submitter_email, + recipient_list, + "Submitter should receive email for public followup.", + ) + finally: + # Restore original setting + setattr( + helpdesk_settings, + "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", + original_setting, + ) + + def test_private_followup_setting_blocks_assigned_user_emails(self): + """Test that HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS also blocks emails to assigned users.""" + # Enable the setting and assign a user to the ticket + original_setting = getattr( + helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False + ) + setattr(helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", True) + + try: + # Assign ticket to a user first + update_ticket( + user=self.update_user, + ticket=self.existing_ticket, + owner=self.assigned_user.id, + public=True, + ) + self.outbox.clear() # Clear assignment emails + + # Now make a private comment - normally this would email the assigned user + update_ticket( + user=self.update_user, + ticket=self.existing_ticket, + comment="This is a private comment for assigned user", + public=False, # Private followup + ) + + email_cnt = len(self.outbox) + self.assertEqual( + email_cnt, + 0, + f"Expected 0 email notifications for private followup when setting is enabled. {email_cnt} were sent.", + ) + finally: + # Restore original setting + setattr( + helpdesk_settings, + "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", + original_setting, + ) + + def test_private_followup_setting_blocks_notify_all_submitter_emails(self): + """Test that HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS blocks emails when NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES is True.""" + # Enable both settings + original_setting = getattr( + helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False + ) + original_notify_all = getattr( + helpdesk_settings, "HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES", False + ) + setattr(helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", True) + setattr( + helpdesk_settings, "HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES", True + ) + + try: + self.outbox.clear() # Clear any existing emails + update_ticket( + user=self.update_user, + ticket=self.existing_ticket, + comment="This is a private comment", + public=False, # Private followup + ) + + email_cnt = len(self.outbox) + # Even though NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES is True, + # HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS should override it + self.assertEqual( + email_cnt, + 0, + f"Expected 0 email notifications for private followup when setting is enabled, even with notify all enabled. {email_cnt} were sent.", + ) + finally: + # Restore original settings + setattr( + helpdesk_settings, + "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", + original_setting, + ) + setattr( + helpdesk_settings, + "HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES", + original_notify_all, + ) + + def test_private_followup_setting_blocks_cc_user_emails(self): + """Test that HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS also blocks emails to CC'd users.""" + from helpdesk.update_ticket import subscribe_to_ticket_updates + + # Enable the setting + original_setting = getattr( + helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", False + ) + setattr(helpdesk_settings, "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", True) + + try: + # Add a CC user to the ticket + cc_user = User.objects.create( + username="cc_user", + email="cc@djangohelpdesk.com", + ) + subscribe_to_ticket_updates( + ticket=self.existing_ticket, user_id=cc_user.id, can_view=True + ) + + self.outbox.clear() # Clear any existing emails + + # Make a private comment - normally this would email CC'd users + update_ticket( + user=self.update_user, + ticket=self.existing_ticket, + comment="This is a private comment that CC users should not see", + public=False, # Private followup + ) + + email_cnt = len(self.outbox) + self.assertEqual( + email_cnt, + 0, + f"Expected 0 email notifications for private followup when setting is enabled (including CC users). {email_cnt} were sent.", + ) + finally: + # Restore original setting + setattr( + helpdesk_settings, + "HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS", + original_setting, + ) diff --git a/helpdesk/update_ticket.py b/helpdesk/update_ticket.py index 626a50e8..8c711743 100644 --- a/helpdesk/update_ticket.py +++ b/helpdesk/update_ticket.py @@ -137,6 +137,10 @@ def process_email_notifications_for_ticket_update( """ Sends email notifications when the ticket is updated in any way. """ + # If the setting is enabled and this is a private follow-up, skip all email notifications + if helpdesk_settings.HELPDESK_PRIVATE_FOLLOWUP_MEANS_NO_EMAILS and not public: + return + template_prefix = get_email_template_prefix(reassigned, follow_up) if helpdesk_settings.HELPDESK_NOTIFY_SUBMITTER_FOR_ALL_TICKET_CHANGES or ( public