diff --git a/templates/zephyr/settings.html b/templates/zephyr/settings.html
index 8c0c886955..b5e9e73510 100644
--- a/templates/zephyr/settings.html
+++ b/templates/zephyr/settings.html
@@ -132,6 +132,17 @@
+
diff --git a/zephyr/lib/actions.py b/zephyr/lib/actions.py
index 1e233a018f..d1cb467447 100644
--- a/zephyr/lib/actions.py
+++ b/zephyr/lib/actions.py
@@ -559,6 +559,14 @@ def do_change_enable_sounds(user_profile, enable_sounds, log=True):
'user': user_profile.email,
'enable_sounds': enable_sounds})
+def do_change_enable_offline_email_notifications(user_profile, offline_email_notifications, log=True):
+ user_profile.enable_offline_email_notifications = offline_email_notifications
+ user_profile.save(update_fields=["enable_offline_email_notifications"])
+ if log:
+ log_event({'type': 'enable_offline_email_notifications_changed',
+ 'user': user_profile.email,
+ 'enable_offline_email_notifications': offline_email_notifications})
+
def do_change_enter_sends(user_profile, enter_sends):
user_profile.enter_sends = enter_sends
user_profile.save(update_fields=["enter_sends"])
@@ -887,6 +895,7 @@ def do_send_confirmation_email(invitee, referrer):
subject_template_path='confirmation/invite_email_subject.txt',
body_template_path='confirmation/invite_email_body.txt')
+@statsd_increment("missed_message_reminders")
def do_send_missedmessage_email(user_profile, missed_messages):
"""
Send a reminder email to a user if she's missed some PMs by being offline
@@ -920,19 +929,12 @@ def do_send_missedmessage_email(user_profile, missed_messages):
user_profile.last_reminder = datetime.datetime.now()
user_profile.save(update_fields=['last_reminder'])
- statsd.incr('missed_message_reminders')
-
def handle_missedmessage_emails(user_profile_id, missed_email_events):
message_ids = [event.get('message_id') for event in missed_email_events]
timestamp = timestamp_to_datetime(event.get('timestamp'))
- try:
- user_profile = UserProfile.objects.get(id=user_profile_id)
- messages = Message.objects.filter(id__in=message_ids, usermessage__flags=~UserMessage.flags.read)
- except (UserProfile.DoesNotExist, Message.DoesNotExist) as e:
- import logging
- logging.warning("Failed to send missed message email, failed to look up: %s %s %e" % \
- (user_profile_id, message_ids, e))
+ user_profile = UserProfile.objects.get(id=user_profile_id)
+ messages = Message.objects.filter(id__in=message_ids, usermessage__flags=~UserMessage.flags.read)
if len(messages) == 0 or timestamp - user_profile.last_reminder < datetime.timedelta(days=1):
# Don't spam the user, if we've sent an email in the last day
diff --git a/zephyr/management/commands/populate_db.py b/zephyr/management/commands/populate_db.py
index b11eef3b77..72f7ad5230 100644
--- a/zephyr/management/commands/populate_db.py
+++ b/zephyr/management/commands/populate_db.py
@@ -553,6 +553,9 @@ def restore_saved_messages():
elif message_type == "enable_sounds_changed":
user_profile = users[old_message["user"]]
user_profile.enable_sounds = (old_message["enable_sounds"] != "false")
+ elif message_type == "enable_offline_email_notifications_changed":
+ user_profile = users[old_message["user"]]
+ user_profile.enable_offline_email_notifications = (old_message["enable_offline_email_notifications"] != "false")
user_profile.save()
continue
elif message_type == "default_streams":
diff --git a/zephyr/static/js/ui.js b/zephyr/static/js/ui.js
index 03663453ad..656846e86b 100644
--- a/zephyr/static/js/ui.js
+++ b/zephyr/static/js/ui.js
@@ -776,6 +776,10 @@ $(function () {
page_params.sounds_enabled = result.enable_sounds;
}
+ if (result.enable_offline_email_notifications !== undefined) {
+ page_params.enable_offline_email_notifications = result.enable_offline_email_notifications;
+ }
+
settings_status.removeClass(status_classes)
.addClass('alert-success')
.text(message).stop(true).fadeTo(0,1);
diff --git a/zephyr/tornado_callbacks.py b/zephyr/tornado_callbacks.py
index 69e2f751f1..0eb4f93d32 100644
--- a/zephyr/tornado_callbacks.py
+++ b/zephyr/tornado_callbacks.py
@@ -2,7 +2,7 @@ from __future__ import absolute_import
from django.conf import settings
from zephyr.models import Message, UserProfile, UserMessage, \
- Recipient, Stream, get_stream
+ Recipient, Stream, get_stream, get_user_profile_by_id
from zephyr.decorator import JsonableError
from zephyr.lib.cache_helpers import cache_get_message
@@ -11,6 +11,7 @@ from zephyr.lib.event_queue import get_client_descriptors_for_user
import os
import sys
+import time
import logging
import requests
import simplejson
@@ -267,6 +268,23 @@ def process_new_message(data):
event = dict(type='message', message=message_dict)
client.add_event(event)
+ # If the recipient was offline and the message was a single or group PM,
+ # potentially notify more immediately
+ if message.recipient.type in (Recipient.PERSONAL, Recipient.HUDDLE) and \
+ user_profile_id != message.sender.id and \
+ len(get_client_descriptors_for_user(user_profile_id)) == 0:
+
+ user_profile = get_user_profile_by_id(user_profile_id)
+
+ if user_profile.enable_offline_email_notifications:
+ event = {"user_profile_id": user_profile_id,
+ "message_id": message.id,
+ "timestamp": time.time()}
+
+ # We require RabbitMQ to do this, as we can't call the email handler
+ # from the Tornado process. So if there's no rabbitmq support do nothing
+ queue_json_publish("missedmessage_emails", event, lambda event: None)
+
if 'stream_name' in data:
stream_receive_message(data['realm_id'], data['stream_name'], message)
diff --git a/zephyr/views.py b/zephyr/views.py
index e131eb79ee..ddbeb7d430 100644
--- a/zephyr/views.py
+++ b/zephyr/views.py
@@ -29,7 +29,7 @@ from zephyr.lib.actions import do_add_subscription, do_remove_subscription, \
create_stream_if_needed, gather_subscriptions, subscribed_to_stream, \
update_user_presence, set_stream_color, get_stream_colors, update_message_flags, \
recipient_for_emails, extract_recipients, do_events_register, do_finish_tutorial, \
- get_status_dict
+ get_status_dict, do_change_enable_offline_email_notifications
from zephyr.forms import RegistrationForm, HomepageForm, ToSForm, is_unique, \
is_inactive, isnt_mit
from django.views.decorators.csrf import csrf_exempt
@@ -521,6 +521,8 @@ def home(request):
user_profile.enable_desktop_notifications,
sounds_enabled =
user_profile.enable_sounds,
+ enable_offline_email_notifications =
+ user_profile.enable_offline_email_notifications,
event_queue_id = register_ret['queue_id'],
last_event_id = register_ret['last_event_id'],
max_message_id = register_ret['max_message_id']
@@ -1283,8 +1285,9 @@ def json_change_settings(request, user_profile, full_name=POST,
# because browsers POST nothing for an unchecked checkbox
enable_desktop_notifications=POST(converter=lambda x: x == "on",
default=False),
- enable_sounds=POST(converter=lambda x: x == "on",
- default=False)):
+ enable_sounds=POST(converter=lambda x: x == "on"),
+ enable_offline_email_notifications=POST(converter=lambda x: x == "on",
+ default=False)):
if new_password != "" or confirm_password != "":
if new_password != confirm_password:
return json_error("New password must match confirmation password!")
@@ -1305,6 +1308,10 @@ def json_change_settings(request, user_profile, full_name=POST,
do_change_enable_sounds(user_profile, enable_sounds)
result['enable_sounds'] = enable_sounds
+ if user_profile.enable_offline_email_notifications != enable_offline_email_notifications:
+ do_change_enable_offline_email_notifications(user_profile, enable_offline_email_notifications)
+ result['enable_offline_email_notifications'] = enable_offline_email_notifications
+
return json_success(result)
@authenticated_json_post_view
@@ -1521,7 +1528,7 @@ def api_github_landing(request, user_profile, event=POST,
# any push notification on a branch that is not in our whitelist.
if short_ref not in re.split('[\s,;|]+', branches):
return json_success()
-
+
subject, content = build_message_from_gitlog(user_profile, repository['name'],
payload['ref'], payload['commits'],