mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-30 19:43:47 +00:00 
			
		
		
		
	welcome-emails: Separate followup_day1 email from other welcome emails.
The initial followup_day1 email confirms that the new user account has been successfully created and should be sent to the user independently of an organization's setting for send_welcome_emails. Here we separate out the followup_day1 email into a separate function from enqueue_welcome_emails and create a helper function for setting the shared welcome email sender information. The followup_day1 email is still a scheduled email so that the initial account creation and log-in process for the user remains unchanged. Fixes #25268.
This commit is contained in:
		
				
					committed by
					
						 Tim Abbott
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							0e1acd595b
						
					
				
				
					commit
					3dfdbbc775
				
			| @@ -19,7 +19,7 @@ from zerver.actions.users import change_user_is_active, get_service_dicts_for_bo | ||||
| from zerver.lib.avatar import avatar_url | ||||
| from zerver.lib.create_user import create_user | ||||
| from zerver.lib.default_streams import get_slim_realm_default_streams | ||||
| from zerver.lib.email_notifications import enqueue_welcome_emails | ||||
| from zerver.lib.email_notifications import enqueue_welcome_emails, send_account_registered_email | ||||
| from zerver.lib.mention import silent_mention_syntax_for_user | ||||
| from zerver.lib.send_email import clear_scheduled_invitation_emails | ||||
| from zerver.lib.stream_subscription import bulk_get_subscriber_peer_info | ||||
| @@ -277,7 +277,11 @@ def process_new_human_user( | ||||
|     # from being sent after the user is created. | ||||
|     clear_scheduled_invitation_emails(user_profile.delivery_email) | ||||
|     if realm.send_welcome_emails: | ||||
|         enqueue_welcome_emails(user_profile, realm_creation) | ||||
|         enqueue_welcome_emails(user_profile) | ||||
|  | ||||
|     # Schedule an initial email with the user's | ||||
|     # new account details and log-in information. | ||||
|     send_account_registered_email(user_profile, realm_creation) | ||||
|  | ||||
|     # We have an import loop here; it's intentional, because we want | ||||
|     # to keep all the onboarding code in zerver/lib/onboarding.py. | ||||
|   | ||||
| @@ -756,38 +756,37 @@ def get_org_type_zulip_guide(realm: Realm) -> Tuple[Any, str]: | ||||
|     return (None, "") | ||||
|  | ||||
|  | ||||
| def enqueue_welcome_emails(user: UserProfile, realm_creation: bool = False) -> None: | ||||
|     from zerver.context_processors import common_context | ||||
|  | ||||
| def welcome_sender_information() -> Tuple[Optional[str], str]: | ||||
|     if settings.WELCOME_EMAIL_SENDER is not None: | ||||
|         # line break to avoid triggering lint rule | ||||
|         from_name = settings.WELCOME_EMAIL_SENDER["name"] | ||||
|         from_address = settings.WELCOME_EMAIL_SENDER["email"] | ||||
|     else: | ||||
|         from_name = None | ||||
|         from_address = FromAddress.support_placeholder | ||||
|  | ||||
|     other_account_count = ( | ||||
|         UserProfile.objects.filter(delivery_email__iexact=user.delivery_email) | ||||
|         .exclude(id=user.id) | ||||
|         .count() | ||||
|     ) | ||||
|     unsubscribe_link = one_click_unsubscribe_link(user, "welcome") | ||||
|     return (from_name, from_address) | ||||
|  | ||||
|  | ||||
| def send_account_registered_email(user: UserProfile, realm_creation: bool = False) -> None: | ||||
|     # Imported here to avoid import cycles. | ||||
|     from zerver.context_processors import common_context | ||||
|  | ||||
|     from_name, from_address = welcome_sender_information() | ||||
|     realm_url = user.realm.uri | ||||
|  | ||||
|     followup_day1_context = common_context(user) | ||||
|     followup_day1_context.update( | ||||
|     account_registered_context = common_context(user) | ||||
|     account_registered_context.update( | ||||
|         realm_creation=realm_creation, | ||||
|         email=user.delivery_email, | ||||
|         is_realm_admin=user.is_realm_admin, | ||||
|         is_demo_org=user.realm.demo_organization_scheduled_deletion_date is not None, | ||||
|     ) | ||||
|  | ||||
|     followup_day1_context["getting_organization_started_link"] = ( | ||||
|     account_registered_context["getting_organization_started_link"] = ( | ||||
|         realm_url + "/help/getting-your-organization-started-with-zulip" | ||||
|     ) | ||||
|  | ||||
|     followup_day1_context["getting_user_started_link"] = ( | ||||
|     account_registered_context["getting_user_started_link"] = ( | ||||
|         realm_url + "/help/getting-started-with-zulip" | ||||
|     ) | ||||
|  | ||||
| @@ -795,13 +794,13 @@ def enqueue_welcome_emails(user: UserProfile, realm_creation: bool = False) -> N | ||||
|     from zproject.backends import ZulipLDAPAuthBackend, email_belongs_to_ldap | ||||
|  | ||||
|     if email_belongs_to_ldap(user.realm, user.delivery_email): | ||||
|         followup_day1_context["ldap"] = True | ||||
|         account_registered_context["ldap"] = True | ||||
|         for backend in get_backends(): | ||||
|             # If the user is doing authentication via LDAP, Note that | ||||
|             # we exclude ZulipLDAPUserPopulator here, since that | ||||
|             # isn't used for authentication. | ||||
|             if isinstance(backend, ZulipLDAPAuthBackend): | ||||
|                 followup_day1_context["ldap_username"] = backend.django_to_ldap_username( | ||||
|                 account_registered_context["ldap_username"] = backend.django_to_ldap_username( | ||||
|                     user.delivery_email | ||||
|                 ) | ||||
|                 break | ||||
| @@ -812,9 +811,23 @@ def enqueue_welcome_emails(user: UserProfile, realm_creation: bool = False) -> N | ||||
|         to_user_ids=[user.id], | ||||
|         from_name=from_name, | ||||
|         from_address=from_address, | ||||
|         context=followup_day1_context, | ||||
|         context=account_registered_context, | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def enqueue_welcome_emails(user: UserProfile) -> None: | ||||
|     # Imported here to avoid import cycles. | ||||
|     from zerver.context_processors import common_context | ||||
|  | ||||
|     from_name, from_address = welcome_sender_information() | ||||
|     other_account_count = ( | ||||
|         UserProfile.objects.filter(delivery_email__iexact=user.delivery_email) | ||||
|         .exclude(id=user.id) | ||||
|         .count() | ||||
|     ) | ||||
|     unsubscribe_link = one_click_unsubscribe_link(user, "welcome") | ||||
|     realm_url = user.realm.uri | ||||
|  | ||||
|     # Any emails scheduled below should be added to the logic in get_onboarding_email_schedule | ||||
|     # to determine how long to delay sending the email based on when the user signed up. | ||||
|     onboarding_email_schedule = get_onboarding_email_schedule(user) | ||||
|   | ||||
| @@ -30,6 +30,7 @@ from zerver.lib.email_notifications import ( | ||||
|     handle_missedmessage_emails, | ||||
|     include_realm_name_in_missedmessage_emails_subject, | ||||
|     relative_to_full_url, | ||||
|     send_account_registered_email, | ||||
| ) | ||||
| from zerver.lib.send_email import FromAddress, deliver_scheduled_emails, send_custom_email | ||||
| from zerver.lib.test_classes import ZulipTestCase | ||||
| @@ -224,7 +225,7 @@ class TestCustomEmails(ZulipTestCase): | ||||
| class TestFollowupEmails(ZulipTestCase): | ||||
|     def test_day1_email_context(self) -> None: | ||||
|         hamlet = self.example_user("hamlet") | ||||
|         enqueue_welcome_emails(hamlet) | ||||
|         send_account_registered_email(hamlet) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=hamlet).order_by( | ||||
|             "scheduled_timestamp" | ||||
|         ) | ||||
| @@ -240,7 +241,7 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|         ScheduledEmail.objects.all().delete() | ||||
|  | ||||
|         iago = self.example_user("iago") | ||||
|         enqueue_welcome_emails(iago) | ||||
|         send_account_registered_email(iago) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=iago).order_by("scheduled_timestamp") | ||||
|         email_data = orjson.loads(scheduled_emails[0].data) | ||||
|         self.assertEqual(email_data["context"]["email"], self.example_email("iago")) | ||||
| @@ -344,6 +345,7 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|         realm = get_realm("zulip") | ||||
|  | ||||
|         # Hamlet has account only in Zulip realm so day1, day2 and zulip_guide emails should be sent | ||||
|         send_account_registered_email(self.example_user("hamlet")) | ||||
|         enqueue_welcome_emails(self.example_user("hamlet")) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=hamlet).order_by( | ||||
|             "scheduled_timestamp" | ||||
| @@ -368,6 +370,7 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|         realm.save() | ||||
|  | ||||
|         # Hamlet is not an admin so the `/for/communities/` zulip_guide should not be sent | ||||
|         send_account_registered_email(self.example_user("hamlet")) | ||||
|         enqueue_welcome_emails(self.example_user("hamlet")) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=hamlet).order_by( | ||||
|             "scheduled_timestamp" | ||||
| @@ -383,6 +386,7 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|         ScheduledEmail.objects.all().delete() | ||||
|  | ||||
|         # Iago is an admin so the `/for/communities/` zulip_guide should be sent | ||||
|         send_account_registered_email(self.example_user("iago")) | ||||
|         enqueue_welcome_emails(self.example_user("iago")) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=iago).order_by("scheduled_timestamp") | ||||
|         self.assert_length(scheduled_emails, 3) | ||||
| @@ -404,6 +408,7 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|         realm.save() | ||||
|  | ||||
|         # Cordelia has account in more than 1 realm so day2 email should not be sent | ||||
|         send_account_registered_email(self.example_user("cordelia")) | ||||
|         enqueue_welcome_emails(self.example_user("cordelia")) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=cordelia).order_by( | ||||
|             "scheduled_timestamp" | ||||
| @@ -428,6 +433,7 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|         realm.save() | ||||
|  | ||||
|         # In this case, Cordelia should only be sent the day1 email | ||||
|         send_account_registered_email(self.example_user("cordelia")) | ||||
|         enqueue_welcome_emails(self.example_user("cordelia")) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=cordelia) | ||||
|         self.assert_length(scheduled_emails, 1) | ||||
| @@ -437,7 +443,8 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|  | ||||
|     def test_followup_emails_for_regular_realms(self) -> None: | ||||
|         cordelia = self.example_user("cordelia") | ||||
|         enqueue_welcome_emails(self.example_user("cordelia"), realm_creation=True) | ||||
|         send_account_registered_email(self.example_user("cordelia"), realm_creation=True) | ||||
|         enqueue_welcome_emails(self.example_user("cordelia")) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=cordelia).order_by( | ||||
|             "scheduled_timestamp" | ||||
|         ) | ||||
| @@ -466,7 +473,8 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|             days=30 | ||||
|         ) | ||||
|         cordelia.realm.save() | ||||
|         enqueue_welcome_emails(self.example_user("cordelia"), realm_creation=True) | ||||
|         send_account_registered_email(self.example_user("cordelia"), realm_creation=True) | ||||
|         enqueue_welcome_emails(self.example_user("cordelia")) | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=cordelia).order_by( | ||||
|             "scheduled_timestamp" | ||||
|         ) | ||||
| @@ -500,10 +508,7 @@ class TestFollowupEmails(ZulipTestCase): | ||||
|             enqueue_welcome_emails(self.example_user("cordelia")) | ||||
|  | ||||
|         scheduled_emails = ScheduledEmail.objects.filter(users=cordelia) | ||||
|         self.assert_length(scheduled_emails, 1) | ||||
|         self.assertEqual( | ||||
|             orjson.loads(scheduled_emails[0].data)["template_prefix"], "zerver/emails/followup_day1" | ||||
|         ) | ||||
|         self.assert_length(scheduled_emails, 0) | ||||
|         self.assertEqual( | ||||
|             m.output, | ||||
|             [f"ERROR:root:Unknown organization type '{invalid_org_type_id}'"], | ||||
| @@ -2185,8 +2190,8 @@ class TestFollowupEmailDelay(ZulipTestCase): | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class TestCustomEmailSender(ZulipTestCase): | ||||
|     def test_custom_email_sender(self) -> None: | ||||
| class TestCustomWelcomeEmailSender(ZulipTestCase): | ||||
|     def test_custom_welcome_email_sender(self) -> None: | ||||
|         name = "Nonreg Email" | ||||
|         email = self.nonreg_email("test") | ||||
|         with override_settings( | ||||
| @@ -2201,6 +2206,5 @@ class TestCustomEmailSender(ZulipTestCase): | ||||
|                 "scheduled_timestamp" | ||||
|             ) | ||||
|             email_data = orjson.loads(scheduled_emails[0].data) | ||||
|             self.assertEqual(email_data["context"]["email"], self.example_email("hamlet")) | ||||
|             self.assertEqual(email_data["from_name"], name) | ||||
|             self.assertEqual(email_data["from_address"], email) | ||||
|   | ||||
| @@ -1134,9 +1134,9 @@ class EmailUnsubscribeTests(ZulipTestCase): | ||||
|         click even when logged out to stop receiving them. | ||||
|         """ | ||||
|         user_profile = self.example_user("hamlet") | ||||
|         # Simulate a new user signing up, which enqueues 3 welcome e-mails. | ||||
|         # Simulate scheduling welcome e-mails for a new user. | ||||
|         enqueue_welcome_emails(user_profile) | ||||
|         self.assertEqual(3, ScheduledEmail.objects.filter(users=user_profile).count()) | ||||
|         self.assertEqual(2, ScheduledEmail.objects.filter(users=user_profile).count()) | ||||
|  | ||||
|         # Simulate unsubscribing from the welcome e-mails. | ||||
|         unsubscribe_link = one_click_unsubscribe_link(user_profile, "welcome") | ||||
|   | ||||
| @@ -13,7 +13,7 @@ from confirmation.models import Confirmation, confirmation_url | ||||
| from zerver.actions.realm_settings import do_send_realm_reactivation_email | ||||
| from zerver.actions.user_settings import do_change_user_delivery_email | ||||
| from zerver.actions.users import change_user_is_active | ||||
| from zerver.lib.email_notifications import enqueue_welcome_emails | ||||
| from zerver.lib.email_notifications import enqueue_welcome_emails, send_account_registered_email | ||||
| from zerver.lib.request import REQ, has_request_variables | ||||
| from zerver.lib.response import json_success | ||||
| from zerver.models import Realm, get_realm, get_realm_stream, get_user_by_delivery_email | ||||
| @@ -137,11 +137,17 @@ def generate_all_emails(request: HttpRequest) -> HttpResponse: | ||||
|     # Reset the email value so we can run this again | ||||
|     do_change_user_delivery_email(user_profile, registered_email) | ||||
|  | ||||
|     # Follow up day1 day2 emails for normal user | ||||
|     # Initial email with new account information for normal user. | ||||
|     send_account_registered_email(user_profile) | ||||
|  | ||||
|     # Follow up day2 and onboarding zulip guide emails for normal user | ||||
|     enqueue_welcome_emails(user_profile) | ||||
|  | ||||
|     # Follow up day1 day2 emails for admin user | ||||
|     enqueue_welcome_emails(get_user_by_delivery_email("iago@zulip.com", realm), realm_creation=True) | ||||
|     # Initial email with new account information for admin user | ||||
|     send_account_registered_email(get_user_by_delivery_email("iago@zulip.com", realm)) | ||||
|  | ||||
|     # Follow up day2 and onboarding zulip guide emails for admin user | ||||
|     enqueue_welcome_emails(get_user_by_delivery_email("iago@zulip.com", realm)) | ||||
|  | ||||
|     # Realm reactivation email | ||||
|     do_send_realm_reactivation_email(realm, acting_user=None) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user