diff --git a/zerver/lib/notifications.py b/zerver/lib/notifications.py index a829a3d5cb..6703329251 100644 --- a/zerver/lib/notifications.py +++ b/zerver/lib/notifications.py @@ -23,7 +23,7 @@ from zerver.models import ( Realm, ) -import datetime +from datetime import timedelta, datetime from email.utils import formataddr import lxml.html import re @@ -31,6 +31,7 @@ import subprocess import ujson import urllib from collections import defaultdict +import pytz def one_click_unsubscribe_link(user_profile: UserProfile, email_type: str) -> str: """ @@ -464,6 +465,25 @@ def log_digest_event(msg: Text) -> None: logging.basicConfig(filename=settings.DIGEST_LOG_PATH, level=logging.INFO) logging.info(msg) +def followup_day2_email_delay(user: UserProfile) -> timedelta: + days_to_delay = 2 + user_tz = user.timezone + if user_tz == '': + user_tz = 'UTC' + signup_day = user.date_joined.astimezone(pytz.timezone(user_tz)).isoweekday() + if signup_day == 5: + # If the day is Friday then delay should be till Monday + days_to_delay = 3 + elif signup_day == 4: + # If the day is Thursday then delay should be till Friday + days_to_delay = 1 + + # The delay should be 1 hour before the above calculated delay as + # our goal is to maximize the chance that this email is near the top + # of the user's inbox when the user sits down to deal with their inbox, + # or comes in while they are dealing with their inbox. + return timedelta(days=days_to_delay, hours=-1) + def enqueue_welcome_emails(user: UserProfile) -> None: from zerver.context_processors import common_context if settings.WELCOME_EMAIL_SENDER is not None: @@ -487,7 +507,7 @@ def enqueue_welcome_emails(user: UserProfile) -> None: from_address=from_address, context=context) send_future_email( "zerver/emails/followup_day2", user.realm, to_user_id=user.id, from_name=from_name, - from_address=from_address, context=context, delay=datetime.timedelta(days=1)) + from_address=from_address, context=context, delay=followup_day2_email_delay(user)) def convert_html_to_markdown(html: Text) -> Text: # On Linux, the tool installs as html2markdown, and there's a command called diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index ead1fb6b49..aa684cd075 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -47,7 +47,7 @@ from zerver.lib.actions import ( from zerver.lib.mobile_auth_otp import xor_hex_strings, ascii_to_hex, \ otp_encrypt_api_key, is_valid_otp, hex_to_ascii, otp_decrypt_api_key from zerver.lib.notifications import enqueue_welcome_emails, \ - one_click_unsubscribe_link + one_click_unsubscribe_link, followup_day2_email_delay from zerver.lib.subdomains import is_root_domain_available from zerver.lib.test_helpers import find_key_by_email, queries_captured, \ HostRequestMock, load_subdomain_token @@ -67,6 +67,7 @@ from typing import Any, Dict, List, Optional, Set, Text import urllib import os +import pytz class RedirectAndLogIntoSubdomainTestCase(ZulipTestCase): def test_cookie_data(self) -> None: @@ -2598,3 +2599,25 @@ class LoginOrAskForRegistrationTestCase(ZulipTestCase): self.assertEqual(user_id, user_profile.id) self.assertEqual(response.status_code, 302) self.assertIn('http://zulip.testserver', response.url) + +class FollowupEmailTest(ZulipTestCase): + def test_followup_day2_email(self) -> None: + user_profile = self.example_user('hamlet') + # Test date_joined == Sunday + user_profile.date_joined = datetime.datetime(2018, 1, 7, 1, 0, 0, 0, pytz.UTC) + self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=2, hours=-1)) + # Test date_joined == Tuesday + user_profile.date_joined = datetime.datetime(2018, 1, 2, 1, 0, 0, 0, pytz.UTC) + self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=2, hours=-1)) + # Test date_joined == Thursday + user_profile.date_joined = datetime.datetime(2018, 1, 4, 1, 0, 0, 0, pytz.UTC) + self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=1, hours=-1)) + # Test date_joined == Friday + user_profile.date_joined = datetime.datetime(2018, 1, 5, 1, 0, 0, 0, pytz.UTC) + self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=3, hours=-1)) + + # Time offset of America/Phoenix is -07:00 + user_profile.timezone = 'America/Phoenix' + # Test date_joined == Friday in UTC, but Thursday in the user's timezone + user_profile.date_joined = datetime.datetime(2018, 1, 5, 1, 0, 0, 0, pytz.UTC) + self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=1, hours=-1))