mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 13:03:29 +00:00
onboarding-emails: Add new onboarding email for organization creator.
Adds a new onboarding email `onboarding_team_to_zulip` for the user who created the new Zulip organization. Co-authored by: Alya Abbott <alya@zulip.com>
This commit is contained in:
committed by
Tim Abbott
parent
ba895b64ef
commit
02d6b3e16d
40
templates/zerver/emails/onboarding_team_to_zulip.html
Normal file
40
templates/zerver/emails/onboarding_team_to_zulip.html
Normal file
@@ -0,0 +1,40 @@
|
||||
{% extends "zerver/emails/email_base_default.html" %}
|
||||
|
||||
{% block illustration %}
|
||||
<img src="{{ email_images_base_url }}/email_logo.png" alt=""/>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<p>
|
||||
{% trans %}If you've already decided to use Zulip for your organization, welcome! You can use our <a href="{{ get_organization_started }}">guide for setting up your organization</a> to get started.{% endtrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% trans %}Otherwise, here is some advice we often hear from customers for evaluating <i>any</i> team chat product:{% endtrans %}
|
||||
<ol>
|
||||
<li>{% trans %}<a href="{{ invite_users }}"><b>Invite your teammates</b></a> to explore with you and share their unique perspectives.{% endtrans %}
|
||||
{% trans %}Use the app itself to chat about your impressions.{% endtrans %}
|
||||
</li>
|
||||
<li>{% trans %}<a href="{{ trying_out_zulip}}"><b>Run a week-long trial</b></a> with your team, without using any other chat tools. This is the only way to truly experience how a new chat app will help your team communicate.{% endtrans %}
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
<p>
|
||||
{% trans %}Zulip is designed to <a href="{{ why_zulip }}">enable efficient communication</a>, and we hope these tips help your team experience it in action.{% endtrans %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% if corporate_enabled %}
|
||||
{{macros.contact_us_zulip_cloud(support_email)}}
|
||||
{% else %}
|
||||
{{macros.contact_us_self_hosted(support_email)}}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block manage_preferences %}
|
||||
|
||||
<p><a href="{{ unsubscribe_link }}">{% trans %}Unsubscribe from welcome emails for {{ realm_name }}{% endtrans %}</a></p>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1 @@
|
||||
{{ _("Choosing the chat app for your team") }}
|
||||
19
templates/zerver/emails/onboarding_team_to_zulip.txt
Normal file
19
templates/zerver/emails/onboarding_team_to_zulip.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
{% trans %}If you've already decided to use Zulip for your organization, welcome! You can use our guide for setting up your organization to get started.{% endtrans %} [ {{ get_organization_started }} ]
|
||||
|
||||
{% trans %}Otherwise, here is some advice we often hear from customers for evaluating any team chat product:{% endtrans %}
|
||||
|
||||
|
||||
1. {% trans %}Invite your teammates to explore with you and share their unique perspectives.{% endtrans %} [ {{ invite_users }} ] {% trans %}Use the app itself to chat about your impressions.{% endtrans %}
|
||||
|
||||
2. {% trans %}Run a week-long trial with your team, without using any other chat tools. This is the only way to truly experience how a new chat app will help your team communicate.{% endtrans %} [ {{ trying_out_zulip }} ]
|
||||
|
||||
{% trans %}Zulip is designed to enable efficient communication, and we hope these tips help your team experience it in action.{% endtrans %} [ {{ why_zulip }} ]
|
||||
|
||||
{% if corporate_enabled %}
|
||||
{% trans %}Do you have questions or feedback to share? Contact us at {{ support_email }} — we'd love to help!{% endtrans %}
|
||||
{% else %}
|
||||
{% trans %}If you have any questions, please contact this Zulip server's administrators at {{ support_email }}.{% endtrans %}
|
||||
{% endif %}
|
||||
|
||||
----
|
||||
{% trans %}Unsubscribe from welcome emails for {{ realm_name }}{% endtrans %}: {{ unsubscribe_link }}
|
||||
@@ -682,6 +682,7 @@ def get_onboarding_email_schedule(user: UserProfile) -> Dict[str, timedelta]:
|
||||
# or comes in while they are dealing with their inbox.
|
||||
"onboarding_zulip_topics": timedelta(days=2, hours=-1),
|
||||
"onboarding_zulip_guide": timedelta(days=4, hours=-1),
|
||||
"onboarding_team_to_zulip": timedelta(days=6, hours=-1),
|
||||
}
|
||||
|
||||
user_tz = user.timezone
|
||||
@@ -693,17 +694,24 @@ def get_onboarding_email_schedule(user: UserProfile) -> Dict[str, timedelta]:
|
||||
# -Do not send emails on Saturday or Sunday
|
||||
# -Have at least one weekday between each (potential) email
|
||||
|
||||
# User signed up on Monday
|
||||
if signup_day == 1:
|
||||
# Send onboarding_team_to_zulip on Tuesday
|
||||
onboarding_emails["onboarding_team_to_zulip"] = timedelta(days=8, hours=-1)
|
||||
|
||||
# User signed up on Tuesday
|
||||
if signup_day == 2:
|
||||
# Send onboarding_zulip_topics on Thursday
|
||||
# Send onboarding_zulip_guide on Monday
|
||||
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
|
||||
# Send onboarding_team_to_zulip on Wednesday
|
||||
onboarding_emails["onboarding_team_to_zulip"] = timedelta(days=8, hours=-1)
|
||||
|
||||
# User signed up on Wednesday
|
||||
if signup_day == 3:
|
||||
# Send onboarding_zulip_topics on Friday
|
||||
# Send onboarding_zulip_guide on Tuesday
|
||||
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
|
||||
# Send onboarding_team_to_zulip on Thursday
|
||||
onboarding_emails["onboarding_team_to_zulip"] = timedelta(days=8, hours=-1)
|
||||
|
||||
# User signed up on Thursday
|
||||
if signup_day == 4:
|
||||
@@ -711,6 +719,8 @@ def get_onboarding_email_schedule(user: UserProfile) -> Dict[str, timedelta]:
|
||||
onboarding_emails["onboarding_zulip_topics"] = timedelta(days=4, hours=-1)
|
||||
# Send onboarding_zulip_guide on Wednesday
|
||||
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
|
||||
# Send onboarding_team_to_zulip on Friday
|
||||
onboarding_emails["onboarding_team_to_zulip"] = timedelta(days=8, hours=-1)
|
||||
|
||||
# User signed up on Friday
|
||||
if signup_day == 5:
|
||||
@@ -718,6 +728,15 @@ def get_onboarding_email_schedule(user: UserProfile) -> Dict[str, timedelta]:
|
||||
onboarding_emails["onboarding_zulip_topics"] = timedelta(days=4, hours=-1)
|
||||
# Send onboarding_zulip_guide on Thursday
|
||||
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
|
||||
# Send onboarding_team_to_zulip on Monday
|
||||
onboarding_emails["onboarding_team_to_zulip"] = timedelta(days=10, hours=-1)
|
||||
|
||||
# User signed up on Saturday; no adjustments needed
|
||||
|
||||
# User signed up on Sunday
|
||||
if signup_day == 7:
|
||||
# Send onboarding_team_to_zulip on Monday
|
||||
onboarding_emails["onboarding_team_to_zulip"] = timedelta(days=8, hours=-1)
|
||||
|
||||
return onboarding_emails
|
||||
|
||||
@@ -881,6 +900,28 @@ def enqueue_welcome_emails(user: UserProfile, realm_creation: bool = False) -> N
|
||||
delay=onboarding_email_schedule["onboarding_zulip_guide"],
|
||||
)
|
||||
|
||||
# We only send the onboarding_team_to_zulip email to user who created the organization.
|
||||
if realm_creation:
|
||||
onboarding_team_to_zulip_context = common_context(user)
|
||||
onboarding_team_to_zulip_context.update(
|
||||
unsubscribe_link=unsubscribe_link,
|
||||
get_organization_started=realm_url
|
||||
+ "/help/getting-your-organization-started-with-zulip",
|
||||
invite_users=realm_url + "/help/invite-users-to-join",
|
||||
trying_out_zulip=realm_url + "/help/trying-out-zulip",
|
||||
why_zulip="https://zulip.com/why-zulip/",
|
||||
)
|
||||
|
||||
send_future_email(
|
||||
"zerver/emails/onboarding_team_to_zulip",
|
||||
user.realm,
|
||||
to_user_ids=[user.id],
|
||||
from_name=from_name,
|
||||
from_address=from_address,
|
||||
context=onboarding_team_to_zulip_context,
|
||||
delay=onboarding_email_schedule["onboarding_team_to_zulip"],
|
||||
)
|
||||
|
||||
|
||||
def convert_html_to_markdown(html: str) -> str:
|
||||
# html2text is GPL licensed, so run it as a subprocess.
|
||||
|
||||
@@ -4635,6 +4635,7 @@ EMAIL_TYPES = {
|
||||
"account_registered": ScheduledEmail.WELCOME,
|
||||
"onboarding_zulip_topics": ScheduledEmail.WELCOME,
|
||||
"onboarding_zulip_guide": ScheduledEmail.WELCOME,
|
||||
"onboarding_team_to_zulip": ScheduledEmail.WELCOME,
|
||||
"digest": ScheduledEmail.DIGEST,
|
||||
"invitation_reminder": ScheduledEmail.INVITATION_REMINDER,
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ class EmailLogTest(ZulipTestCase):
|
||||
output_log = (
|
||||
"INFO:root:Emails sent in development are available at http://testserver/emails"
|
||||
)
|
||||
self.assertEqual(m.output, [output_log for i in range(17)])
|
||||
self.assertEqual(m.output, [output_log for i in range(18)])
|
||||
|
||||
def test_forward_address_details(self) -> None:
|
||||
try:
|
||||
|
||||
@@ -482,12 +482,12 @@ class TestFollowupEmails(ZulipTestCase):
|
||||
def test_followup_emails_for_regular_realms(self) -> None:
|
||||
cordelia = self.example_user("cordelia")
|
||||
send_account_registered_email(self.example_user("cordelia"), realm_creation=True)
|
||||
enqueue_welcome_emails(self.example_user("cordelia"))
|
||||
enqueue_welcome_emails(self.example_user("cordelia"), realm_creation=True)
|
||||
scheduled_emails = ScheduledEmail.objects.filter(users=cordelia).order_by(
|
||||
"scheduled_timestamp"
|
||||
)
|
||||
assert scheduled_emails is not None
|
||||
self.assert_length(scheduled_emails, 2)
|
||||
self.assert_length(scheduled_emails, 3)
|
||||
self.assertEqual(
|
||||
orjson.loads(scheduled_emails[0].data)["template_prefix"],
|
||||
"zerver/emails/account_registered",
|
||||
@@ -496,6 +496,10 @@ class TestFollowupEmails(ZulipTestCase):
|
||||
orjson.loads(scheduled_emails[1].data)["template_prefix"],
|
||||
"zerver/emails/onboarding_zulip_guide",
|
||||
)
|
||||
self.assertEqual(
|
||||
orjson.loads(scheduled_emails[2].data)["template_prefix"],
|
||||
"zerver/emails/onboarding_team_to_zulip",
|
||||
)
|
||||
|
||||
deliver_scheduled_emails(scheduled_emails[0])
|
||||
from django.core.mail import outbox
|
||||
@@ -513,12 +517,12 @@ class TestFollowupEmails(ZulipTestCase):
|
||||
)
|
||||
cordelia.realm.save()
|
||||
send_account_registered_email(self.example_user("cordelia"), realm_creation=True)
|
||||
enqueue_welcome_emails(self.example_user("cordelia"))
|
||||
enqueue_welcome_emails(self.example_user("cordelia"), realm_creation=True)
|
||||
scheduled_emails = ScheduledEmail.objects.filter(users=cordelia).order_by(
|
||||
"scheduled_timestamp"
|
||||
)
|
||||
assert scheduled_emails is not None
|
||||
self.assert_length(scheduled_emails, 2)
|
||||
self.assert_length(scheduled_emails, 3)
|
||||
self.assertEqual(
|
||||
orjson.loads(scheduled_emails[0].data)["template_prefix"],
|
||||
"zerver/emails/account_registered",
|
||||
@@ -527,6 +531,10 @@ class TestFollowupEmails(ZulipTestCase):
|
||||
orjson.loads(scheduled_emails[1].data)["template_prefix"],
|
||||
"zerver/emails/onboarding_zulip_guide",
|
||||
)
|
||||
self.assertEqual(
|
||||
orjson.loads(scheduled_emails[2].data)["template_prefix"],
|
||||
"zerver/emails/onboarding_team_to_zulip",
|
||||
)
|
||||
|
||||
deliver_scheduled_emails(scheduled_emails[0])
|
||||
from django.core.mail import outbox
|
||||
@@ -562,6 +570,7 @@ class TestOnboardingEmailDelay(ZulipTestCase):
|
||||
date_joined: str,
|
||||
onboarding_zulip_topics: int,
|
||||
onboarding_zulip_guide: int,
|
||||
onboarding_team_to_zulip: int,
|
||||
) -> None:
|
||||
DAY_OF_WEEK = {
|
||||
"Monday": datetime(2018, 1, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
|
||||
@@ -591,35 +600,43 @@ class TestOnboardingEmailDelay(ZulipTestCase):
|
||||
self.assertEqual(day_sent, onboarding_zulip_guide)
|
||||
self.assertNotIn(day_sent, WEEKEND)
|
||||
|
||||
# onboarding_team_to_zulip
|
||||
day_sent = (
|
||||
DAY_OF_WEEK[date_joined] + onboarding_email_schedule["onboarding_team_to_zulip"]
|
||||
).isoweekday()
|
||||
self.assertEqual(day_sent, onboarding_team_to_zulip)
|
||||
self.assertNotIn(day_sent, WEEKEND)
|
||||
|
||||
def test_get_onboarding_email_schedule(self) -> None:
|
||||
user_profile = self.example_user("hamlet")
|
||||
|
||||
# joined Monday: schedule = Wednesday:3, Friday:5,
|
||||
self.verify_onboarding_email_schedule(user_profile, "Monday", 3, 5)
|
||||
# joined Monday: schedule = Wednesday:3, Friday:5, Tuesday:2
|
||||
self.verify_onboarding_email_schedule(user_profile, "Monday", 3, 5, 2)
|
||||
|
||||
# joined Tuesday: schedule = Thursday:4, Monday:1
|
||||
self.verify_onboarding_email_schedule(user_profile, "Tuesday", 4, 1)
|
||||
# joined Tuesday: schedule = Thursday:4, Monday:1, Wednesday:3
|
||||
self.verify_onboarding_email_schedule(user_profile, "Tuesday", 4, 1, 3)
|
||||
|
||||
# joined Wednesday: schedule = Friday:5, Tuesday:2
|
||||
self.verify_onboarding_email_schedule(user_profile, "Wednesday", 5, 2)
|
||||
# joined Wednesday: schedule = Friday:5, Tuesday:2, Thursday:4
|
||||
self.verify_onboarding_email_schedule(user_profile, "Wednesday", 5, 2, 4)
|
||||
|
||||
# joined Thursday: schedule = Monday:1, Wednesday:3
|
||||
self.verify_onboarding_email_schedule(user_profile, "Thursday", 1, 3)
|
||||
# joined Thursday: schedule = Monday:1, Wednesday:3, Friday:5
|
||||
self.verify_onboarding_email_schedule(user_profile, "Thursday", 1, 3, 5)
|
||||
|
||||
# joined Friday: schedule = Tuesday:2, Thursday:4
|
||||
self.verify_onboarding_email_schedule(user_profile, "Friday", 2, 4)
|
||||
# joined Friday: schedule = Tuesday:2, Thursday:4, Monday:1
|
||||
self.verify_onboarding_email_schedule(user_profile, "Friday", 2, 4, 1)
|
||||
|
||||
# joined Saturday: schedule = Monday:1, Wednesday:3
|
||||
self.verify_onboarding_email_schedule(user_profile, "Saturday", 1, 3)
|
||||
# joined Saturday: schedule = Monday:1, Wednesday:3, Friday:5
|
||||
self.verify_onboarding_email_schedule(user_profile, "Saturday", 1, 3, 5)
|
||||
|
||||
# joined Sunday: schedule = Tuesday:2, Thursday:4
|
||||
self.verify_onboarding_email_schedule(user_profile, "Sunday", 2, 4)
|
||||
# joined Sunday: schedule = Tuesday:2, Thursday:4, Monday:1
|
||||
self.verify_onboarding_email_schedule(user_profile, "Sunday", 2, 4, 1)
|
||||
|
||||
def test_time_offset_for_onboarding_email_schedule(self) -> None:
|
||||
user_profile = self.example_user("hamlet")
|
||||
days_delayed = {
|
||||
"4": timedelta(days=4, hours=-1),
|
||||
"6": timedelta(days=6, hours=-1),
|
||||
"8": timedelta(days=8, hours=-1),
|
||||
}
|
||||
|
||||
# Time offset of America/Phoenix is -07:00
|
||||
@@ -641,6 +658,12 @@ class TestOnboardingEmailDelay(ZulipTestCase):
|
||||
days_delayed["6"],
|
||||
)
|
||||
|
||||
# onboarding_team_to_zulip sent on Friday
|
||||
self.assertEqual(
|
||||
onboarding_email_schedule["onboarding_team_to_zulip"],
|
||||
days_delayed["8"],
|
||||
)
|
||||
|
||||
|
||||
class TestCustomWelcomeEmailSender(ZulipTestCase):
|
||||
def test_custom_welcome_email_sender(self) -> None:
|
||||
|
||||
@@ -402,7 +402,7 @@ class TestDevelopmentEmailsLog(ZulipTestCase):
|
||||
"INFO:root:Emails sent in development are available at http://testserver/emails"
|
||||
)
|
||||
# logger.output is a list of all the log messages captured. Verify it is as expected.
|
||||
self.assertEqual(logger.output, [output_log] * 17)
|
||||
self.assertEqual(logger.output, [output_log] * 18)
|
||||
|
||||
# Now, lets actually go the URL the above call redirects to, i.e., /emails/
|
||||
result = self.client_get(result["Location"])
|
||||
|
||||
@@ -147,7 +147,7 @@ def generate_all_emails(request: HttpRequest) -> HttpResponse:
|
||||
send_account_registered_email(get_user_by_delivery_email("iago@zulip.com", realm))
|
||||
|
||||
# Onboarding emails for admin user
|
||||
enqueue_welcome_emails(get_user_by_delivery_email("iago@zulip.com", realm))
|
||||
enqueue_welcome_emails(get_user_by_delivery_email("iago@zulip.com", realm), realm_creation=True)
|
||||
|
||||
# Realm reactivation email
|
||||
do_send_realm_reactivation_email(realm, acting_user=None)
|
||||
|
||||
Reference in New Issue
Block a user