def test_email_translation(self) -> None: def check_translation(phrase: str, request_type: str, *args: Any, **kwargs: Any) -> None: if request_type == "post": self.client_post(*args, **kwargs) elif request_type == "patch": # nocoverage: see comment below self.client_patch(*args, **kwargs) email_message = mail.outbox[0] self.assertIn(phrase, email_message.body) for i in range(len(mail.outbox)): mail.outbox.pop() hamlet = self.example_user("hamlet") hamlet.default_language = "de" hamlet.save() realm = hamlet.realm realm.default_language = "de" realm.save() self.login(hamlet.email) # TODO: Uncomment and replace with translation once we have German translations for the strings # in confirm_new_email.txt. # Also remove the "nocoverage" from check_translation above. # check_translation("Viele Grüße", "patch", "/json/settings", {"email": "*****@*****.**"}) check_translation("Incrível!", "post", "/accounts/home/", {"email": "*****@*****.**"}, HTTP_ACCEPT_LANGUAGE="pt") check_translation("Danke, dass Du", "post", '/accounts/find/', {'emails': hamlet.email}) check_translation("Hallo", "post", "/json/invites", {"invitee_emails": "*****@*****.**", "stream": ["Denmark"]}) with self.settings(DEVELOPMENT_LOG_EMAILS=True): enqueue_welcome_emails(hamlet) check_translation("Viele Grüße", "")
def consume(self, data): # type: (Mapping[str, Any]) -> None # This should clear out any invitation reminder emails clear_followup_emails_queue(data['email_address']) realm = Realm.objects.get(id=data['merge_fields']['REALM_ID']) if settings.MAILCHIMP_API_KEY and settings.PRODUCTION: endpoint = "https://%s.api.mailchimp.com/3.0/lists/%s/members" % \ (settings.MAILCHIMP_API_KEY.split('-')[1], settings.ZULIP_FRIENDS_LIST_ID) params = dict(data) params['list_id'] = settings.ZULIP_FRIENDS_LIST_ID params['status'] = 'subscribed' r = requests.post(endpoint, auth=('apikey', settings.MAILCHIMP_API_KEY), json=params, timeout=10) if r.status_code == 400 and ujson.loads( r.text)['title'] == 'Member Exists': logging.warning( "Attempted to sign up already existing email to list: %s" % (data['email_address'], )) else: r.raise_for_status() enqueue_welcome_emails(data['email_address'], data['merge_fields']['NAME'], realm)
def test_day1_email_context(self) -> None: hamlet = self.example_user("hamlet") enqueue_welcome_emails(hamlet) scheduled_emails = ScheduledEmail.objects.filter(user=hamlet) email_data = ujson.loads(scheduled_emails[0].data) self.assertEqual(email_data["context"]["email"], self.example_email("hamlet")) self.assertEqual(email_data["context"]["is_realm_admin"], False) self.assertEqual(email_data["context"]["getting_started_link"], "https://zulipchat.com") self.assertNotIn("ldap_username", email_data["context"]) ScheduledEmail.objects.all().delete() iago = self.example_user("iago") enqueue_welcome_emails(iago) scheduled_emails = ScheduledEmail.objects.filter(user=iago) email_data = ujson.loads(scheduled_emails[0].data) self.assertEqual(email_data["context"]["email"], self.example_email("iago")) self.assertEqual(email_data["context"]["is_realm_admin"], True) self.assertEqual( email_data["context"]["getting_started_link"], "http://zulip.testserver/help/getting-your-organization-started-with-zulip" ) self.assertNotIn("ldap_username", email_data["context"])
def test_welcome_unsubscribe(self): """ We provide one-click unsubscribe links in welcome e-mails that you can click even when logged out to stop receiving them. """ email = "*****@*****.**" user_profile = get_user_profile_by_email("*****@*****.**") # Simulate a new user signing up, which enqueues 2 welcome e-mails. enqueue_welcome_emails(email, "King Hamlet") self.assertEqual( 2, len( ScheduledJob.objects.filter(type=ScheduledJob.EMAIL, filter_string__iexact=email))) # Simulate unsubscribing from the welcome e-mails. unsubscribe_link = one_click_unsubscribe_link(user_profile, "welcome") result = self.client.get(urlparse(unsubscribe_link).path) # The welcome email jobs are no longer scheduled. self.assertEqual(result.status_code, 200) self.assertEqual( 0, len( ScheduledJob.objects.filter(type=ScheduledJob.EMAIL, filter_string__iexact=email)))
def generate_all_emails(request: HttpRequest) -> HttpResponse: # write fake data for all variables registered_email = "*****@*****.**" unregistered_email_1 = "*****@*****.**" unregistered_email_2 = "*****@*****.**" realm = get_realm("zulip") host_kwargs = {'HTTP_HOST': realm.host} # Password reset email result = client.post('/accounts/password/reset/', {'email': registered_email}, **host_kwargs) assert result.status_code == 302 # Confirm account email result = client.post('/accounts/home/', {'email': unregistered_email_1}, **host_kwargs) assert result.status_code == 302 # Find account email result = client.post('/accounts/find/', {'emails': registered_email}, **host_kwargs) assert result.status_code == 302 # New login email logged_in = client.login(dev_auth_username=registered_email, realm=realm) assert logged_in # New user invite and reminder emails result = client.post( "/json/invites", { "invitee_emails": unregistered_email_2, "stream": ["Denmark"], "custom_body": "" }, **host_kwargs) assert result.status_code == 200 # Verification for new email result = client.patch( '/json/settings', urllib.parse.urlencode({'email': '*****@*****.**'}), **host_kwargs) assert result.status_code == 200 # Email change successful key = Confirmation.objects.filter( type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key url = confirmation_url(key, realm.host, Confirmation.EMAIL_CHANGE) user_profile = get_user(registered_email, realm) result = client.get(url) assert result.status_code == 200 # Reset the email value so we can run this again user_profile.email = registered_email user_profile.save(update_fields=['email']) # Follow up day1 day2 emails enqueue_welcome_emails(user_profile) return redirect(email_page)
def generate_all_emails(request): # type: (HttpRequest) -> HttpResponse # write fake data for all variables registered_email = "*****@*****.**" unregistered_email_1 = "*****@*****.**" unregistered_email_2 = "*****@*****.**" realm = get_realm("zulip") host_kwargs = {'HTTP_HOST': realm.host} # Password reset email client.post('/accounts/password/reset/', {'email': registered_email}, **host_kwargs) # Confirm account email client.post('/accounts/home/', {'email': unregistered_email_1}, **host_kwargs) # Find account email client.post('/accounts/find/', {'emails': registered_email}, **host_kwargs) # New login email client.login(username=registered_email) # New user invite and reminder emails client.post( "/json/invites", { "invitee_emails": unregistered_email_2, "stream": ["Denmark"], "custom_body": "" }, **host_kwargs) # Verification for new email client.patch('/json/settings', urllib.parse.urlencode({'email': '*****@*****.**'}), **host_kwargs) # Email change successful key = Confirmation.objects.filter( type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key url = confirmation_url(key, realm.host, Confirmation.EMAIL_CHANGE) user_profile = get_user(registered_email, realm) client.get(url) user_profile.emails = "*****@*****.**" user_profile.save() # Follow up day1 day2 emails enqueue_welcome_emails(user_profile) message = ''' Emails generated successfully. Reload this page to generate them again. To clear this log click <a href="/emails/clear">here</a>. ''' return email_page(request, message)
def generate_all_emails(request: HttpRequest) -> HttpResponse: # write fake data for all variables registered_email = "*****@*****.**" unregistered_email_1 = "*****@*****.**" unregistered_email_2 = "*****@*****.**" realm = get_realm("zulip") host_kwargs = {'HTTP_HOST': realm.host} # Password reset email result = client.post('/accounts/password/reset/', {'email': registered_email}, **host_kwargs) assert result.status_code == 302 # Confirm account email result = client.post('/accounts/home/', {'email': unregistered_email_1}, **host_kwargs) assert result.status_code == 302 # Find account email result = client.post('/accounts/find/', {'emails': registered_email}, **host_kwargs) assert result.status_code == 302 # New login email logged_in = client.login(dev_auth_username=registered_email, realm=realm) assert logged_in # New user invite and reminder emails result = client.post("/json/invites", {"invitee_emails": unregistered_email_2, "stream": ["Denmark"]}, **host_kwargs) assert result.status_code == 200 # Verification for new email result = client.patch('/json/settings', urllib.parse.urlencode({'email': '*****@*****.**'}), **host_kwargs) assert result.status_code == 200 # Email change successful key = Confirmation.objects.filter(type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key url = confirmation_url(key, realm.host, Confirmation.EMAIL_CHANGE) user_profile = get_user(registered_email, realm) result = client.get(url) assert result.status_code == 200 # Reset the email value so we can run this again user_profile.email = registered_email user_profile.save(update_fields=['email']) # Follow up day1 day2 emails enqueue_welcome_emails(user_profile) return redirect(email_page)
class SignupWorker(QueueProcessingWorker): def __init__(self): super(SignupWorker, self).__init__() if settings.MAILCHIMP_API_KEY: self.pm = PostMonkey(settings.MAILCHIMP_API_KEY, timeout=10) def consume(self, data): merge_vars=data['merge_vars'] # This should clear out any invitation reminder emails clear_followup_emails_queue(data["EMAIL"]) if settings.MAILCHIMP_API_KEY and settings.PRODUCTION: try: self.pm.listSubscribe( id=settings.ZULIP_FRIENDS_LIST_ID, email_address=data['EMAIL'], merge_vars=merge_vars, double_optin=False, send_welcome=False) except MailChimpException, e: if e.code == 214: logging.warning("Attempted to sign up already existing email to list: %s" % (data['EMAIL'],)) else: raise e email = data.get("EMAIL") name = merge_vars.get("NAME") enqueue_welcome_emails(email, name)
def consume(self, data): # type: (Mapping[str, Any]) -> None # This should clear out any invitation reminder emails clear_followup_emails_queue(data['email_address']) if settings.MAILCHIMP_API_KEY and settings.PRODUCTION: endpoint = "https://%s.api.mailchimp.com/3.0/lists/%s/members" % \ (settings.MAILCHIMP_API_KEY.split('-')[1], settings.ZULIP_FRIENDS_LIST_ID) params = dict(data) params['list_id'] = settings.ZULIP_FRIENDS_LIST_ID params['status'] = 'subscribed' r = requests.post(endpoint, auth=('apikey', settings.MAILCHIMP_API_KEY), json=params, timeout=10) if r.status_code == 400 and ujson.loads(r.text)['title'] == 'Member Exists': logging.warning("Attempted to sign up already existing email to list: %s" % (data['email_address'],)) else: r.raise_for_status() enqueue_welcome_emails(data['email_address'], data['merge_fields']['NAME'])
def consume(self, data): # type: (Mapping[str, Any]) -> None clear_scheduled_emails(data['user_id'], ScheduledEmail.INVITATION_REMINDER) if settings.MAILCHIMP_API_KEY and settings.PRODUCTION: endpoint = "https://%s.api.mailchimp.com/3.0/lists/%s/members" % \ (settings.MAILCHIMP_API_KEY.split('-')[1], settings.ZULIP_FRIENDS_LIST_ID) params = dict(data) del params['user_id'] params['list_id'] = settings.ZULIP_FRIENDS_LIST_ID params['status'] = 'subscribed' r = requests.post(endpoint, auth=('apikey', settings.MAILCHIMP_API_KEY), json=params, timeout=10) if r.status_code == 400 and ujson.loads(r.text)['title'] == 'Member Exists': logging.warning("Attempted to sign up already existing email to list: %s" % (data['email_address'],)) else: r.raise_for_status() enqueue_welcome_emails(data['user_id'])
def test_followup_emails_count(self) -> None: hamlet = self.example_user("hamlet") cordelia = self.example_user("cordelia") enqueue_welcome_emails(self.example_user("hamlet")) # Hamlet has account only in Zulip realm so both day1 and day2 emails should be sent scheduled_emails = ScheduledEmail.objects.filter(user=hamlet) self.assertEqual(2, len(scheduled_emails)) self.assertEqual(ujson.loads(scheduled_emails[0].data)["template_prefix"], 'zerver/emails/followup_day2') self.assertEqual(ujson.loads(scheduled_emails[1].data)["template_prefix"], 'zerver/emails/followup_day1') ScheduledEmail.objects.all().delete() enqueue_welcome_emails(cordelia) scheduled_emails = ScheduledEmail.objects.filter(user=cordelia) # Cordelia has account in more than 1 realm so day2 email should not be sent self.assertEqual(len(scheduled_emails), 1) email_data = ujson.loads(scheduled_emails[0].data) self.assertEqual(email_data["template_prefix"], 'zerver/emails/followup_day1')
def test_email_translation(self) -> None: def check_translation(phrase: str, request_type: str, *args: Any, **kwargs: Any) -> None: if request_type == "post": self.client_post(*args, **kwargs) elif request_type == "patch": # nocoverage: see comment below self.client_patch(*args, **kwargs) email_message = mail.outbox[0] self.assertIn(phrase, email_message.body) for i in range(len(mail.outbox)): mail.outbox.pop() hamlet = self.example_user("hamlet") hamlet.default_language = "de" hamlet.save() realm = hamlet.realm realm.default_language = "de" realm.save() stream = get_realm_stream("Denmark", realm.id) self.login(hamlet.email) # TODO: Uncomment and replace with translation once we have German translations for the strings # in confirm_new_email.txt. # Also remove the "nocoverage" from check_translation above. # check_translation("Viele Grüße", "patch", "/json/settings", {"email": "*****@*****.**"}) check_translation("Incrível!", "post", "/accounts/home/", {"email": "*****@*****.**"}, HTTP_ACCEPT_LANGUAGE="pt") check_translation("Danke, dass Du", "post", '/accounts/find/', {'emails': hamlet.email}) check_translation( "Hallo", "post", "/json/invites", { "invitee_emails": "*****@*****.**", "stream_ids": ujson.dumps([stream.id]) }) with self.settings(DEVELOPMENT_LOG_EMAILS=True): enqueue_welcome_emails(hamlet) check_translation("Viele Grüße", "")
def consume(self, data): merge_vars=data['merge_vars'] # This should clear out any invitation reminder emails clear_followup_emails_queue(data["EMAIL"]) if settings.MAILCHIMP_API_KEY and settings.PRODUCTION: try: self.pm.listSubscribe( id=settings.ZULIP_FRIENDS_LIST_ID, email_address=data['EMAIL'], merge_vars=merge_vars, double_optin=False, send_welcome=False) except MailChimpException as e: if e.code == 214: logging.warning("Attempted to sign up already existing email to list: %s" % (data['EMAIL'],)) else: raise e email = data.get("EMAIL") name = merge_vars.get("NAME") enqueue_welcome_emails(email, name)
def test_day1_email_context(self) -> None: hamlet = self.example_user("hamlet") enqueue_welcome_emails(hamlet) scheduled_emails = ScheduledEmail.objects.filter(user=hamlet) email_data = ujson.loads(scheduled_emails[0].data) self.assertEqual(email_data["context"]["email"], self.example_email("hamlet")) self.assertEqual(email_data["context"]["is_realm_admin"], False) self.assertEqual(email_data["context"]["getting_started_link"], "https://zulipchat.com") self.assertNotIn("ldap_username", email_data["context"]) ScheduledEmail.objects.all().delete() iago = self.example_user("iago") enqueue_welcome_emails(iago) scheduled_emails = ScheduledEmail.objects.filter(user=iago) email_data = ujson.loads(scheduled_emails[0].data) self.assertEqual(email_data["context"]["email"], self.example_email("iago")) self.assertEqual(email_data["context"]["is_realm_admin"], True) self.assertEqual(email_data["context"]["getting_started_link"], "http://zulip.testserver/help/getting-your-organization-started-with-zulip") self.assertNotIn("ldap_username", email_data["context"])
def test_welcome_unsubscribe(self): """ We provide one-click unsubscribe links in welcome e-mails that you can click even when logged out to stop receiving them. """ email = "*****@*****.**" user_profile = get_user_profile_by_email("*****@*****.**") # Simulate a new user signing up, which enqueues 2 welcome e-mails. enqueue_welcome_emails(email, "King Hamlet") self.assertEqual(2, len(ScheduledJob.objects.filter( type=ScheduledJob.EMAIL, filter_string__iexact=email))) # Simulate unsubscribing from the welcome e-mails. unsubscribe_link = one_click_unsubscribe_link(user_profile, "welcome") result = self.client.get(urllib.parse.urlparse(unsubscribe_link).path) # The welcome email jobs are no longer scheduled. self.assertEqual(result.status_code, 200) self.assertEqual(0, len(ScheduledJob.objects.filter( type=ScheduledJob.EMAIL, filter_string__iexact=email)))
def consume(self, data): # type: (Mapping[str, Any]) -> None merge_vars=data['merge_vars'] # This should clear out any invitation reminder emails clear_followup_emails_queue(data["EMAIL"]) if settings.MAILCHIMP_API_KEY and settings.PRODUCTION: try: self.pm.listSubscribe( id=settings.ZULIP_FRIENDS_LIST_ID, email_address=data['EMAIL'], merge_vars=merge_vars, double_optin=False, send_welcome=False) except MailChimpException as e: if e.code == 214: logging.warning("Attempted to sign up already existing email to list: %s" % (data['EMAIL'],)) else: raise e email = data.get("EMAIL") name = merge_vars.get("NAME") enqueue_welcome_emails(email, name)
def test_email_translation(self) -> None: def check_translation(phrase: str, request_type: str, *args: Any, **kwargs: Any) -> None: if request_type == "post": self.client_post(*args, **kwargs) elif request_type == "patch": self.client_patch(*args, **kwargs) email_message = mail.outbox[0] self.assertIn(phrase, email_message.body) for i in range(len(mail.outbox)): mail.outbox.pop() hamlet = self.example_user("hamlet") hamlet.default_language = "de" hamlet.save() realm = hamlet.realm realm.default_language = "de" realm.save() self.login(hamlet.email) check_translation("Viele Grüße", "patch", "/json/settings", {"email": "*****@*****.**"}) check_translation("Incrível!", "post", "/accounts/home/", {"email": "*****@*****.**"}, HTTP_ACCEPT_LANGUAGE="pt") check_translation("Danke, dass Du", "post", '/accounts/find/', {'emails': hamlet.email}) check_translation("Hallo", "post", "/json/invites", { "invitee_emails": "*****@*****.**", "stream": ["Denmark"] }) with self.settings(DEVELOPMENT_LOG_EMAILS=True): enqueue_welcome_emails(hamlet) check_translation("Viele Grüße", "")
def generate_all_emails(request: HttpRequest) -> HttpResponse: if not settings.TEST_SUITE: # nocoverage # It's really convenient to automatically inline the email CSS # here, since that saves a step when testing out changes to # the email CSS. But we don't run this inside the test suite, # because by role, the tests shouldn't be doing a provision-like thing. subprocess.check_call(["./tools/inline-email-css"]) # We import the Django test client inside the view function, # because it isn't needed in production elsewhere, and not # importing it saves ~50ms of unnecessary manage.py startup time. from django.test import Client client = Client() # write fake data for all variables registered_email = "*****@*****.**" unregistered_email_1 = "*****@*****.**" unregistered_email_2 = "*****@*****.**" realm = get_realm("zulip") host_kwargs = {'HTTP_HOST': realm.host} # Password reset email result = client.post('/accounts/password/reset/', {'email': registered_email}, **host_kwargs) assert result.status_code == 302 # Confirm account email result = client.post('/accounts/home/', {'email': unregistered_email_1}, **host_kwargs) assert result.status_code == 302 # Find account email result = client.post('/accounts/find/', {'emails': registered_email}, **host_kwargs) assert result.status_code == 302 # New login email logged_in = client.login(dev_auth_username=registered_email, realm=realm) assert logged_in # New user invite and reminder emails result = client.post("/json/invites", { "invitee_emails": unregistered_email_2, "stream": ["Denmark"] }, **host_kwargs) assert result.status_code == 200 # Verification for new email result = client.patch( '/json/settings', urllib.parse.urlencode({'email': '*****@*****.**'}), **host_kwargs) assert result.status_code == 200 # Email change successful key = Confirmation.objects.filter( type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key url = confirmation_url(key, realm.host, Confirmation.EMAIL_CHANGE) user_profile = get_user_by_delivery_email(registered_email, realm) result = client.get(url) assert result.status_code == 200 # Reset the email value so we can run this again user_profile.email = registered_email user_profile.save(update_fields=['email']) # Follow up day1 day2 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("*****@*****.**", realm), realm_creation=True) return redirect(email_page)
def generate_all_emails(request: HttpRequest) -> HttpResponse: if not settings.TEST_SUITE: # nocoverage # It's really convenient to automatically inline the email CSS # here, since that saves a step when testing out changes to # the email CSS. But we don't run this inside the test suite, # because by role, the tests shouldn't be doing a provision-like thing. subprocess.check_call(["./tools/inline-email-css"]) # We import the Django test client inside the view function, # because it isn't needed in production elsewhere, and not # importing it saves ~50ms of unnecessary manage.py startup time. from django.test import Client client = Client() # write fake data for all variables registered_email = "*****@*****.**" unregistered_email_1 = "*****@*****.**" unregistered_email_2 = "*****@*****.**" realm = get_realm("zulip") other_realm = Realm.objects.exclude(string_id='zulip').first() user = get_user_by_delivery_email(registered_email, realm) host_kwargs = {'HTTP_HOST': realm.host} # Password reset emails # active account in realm result = client.post('/accounts/password/reset/', {'email': registered_email}, **host_kwargs) assert result.status_code == 302 # deactivated user user.is_active = False user.save(update_fields=['is_active']) result = client.post('/accounts/password/reset/', {'email': registered_email}, **host_kwargs) assert result.status_code == 302 user.is_active = True user.save(update_fields=['is_active']) # account on different realm result = client.post('/accounts/password/reset/', {'email': registered_email}, HTTP_HOST=other_realm.host) assert result.status_code == 302 # no account anywhere result = client.post('/accounts/password/reset/', {'email': unregistered_email_1}, **host_kwargs) assert result.status_code == 302 # Confirm account email result = client.post('/accounts/home/', {'email': unregistered_email_1}, **host_kwargs) assert result.status_code == 302 # Find account email result = client.post('/accounts/find/', {'emails': registered_email}, **host_kwargs) assert result.status_code == 302 # New login email logged_in = client.login(dev_auth_username=registered_email, realm=realm) assert logged_in # New user invite and reminder emails result = client.post("/json/invites", {"invitee_emails": unregistered_email_2, "stream": ["Denmark"]}, **host_kwargs) assert result.status_code == 200 # Verification for new email result = client.patch('/json/settings', urllib.parse.urlencode({'email': '*****@*****.**'}), **host_kwargs) assert result.status_code == 200 # Email change successful key = Confirmation.objects.filter(type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key url = confirmation_url(key, realm.host, Confirmation.EMAIL_CHANGE) user_profile = get_user_by_delivery_email(registered_email, realm) result = client.get(url) assert result.status_code == 200 # 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 enqueue_welcome_emails(user_profile) # Follow up day1 day2 emails for admin user enqueue_welcome_emails(get_user_by_delivery_email("*****@*****.**", realm), realm_creation=True) # Realm reactivation email do_send_realm_reactivation_email(realm) return redirect(email_page)