Add a one-click unsubscribe link to missed message e-mails.

(imported from commit 719eb61c9b7722eb1b0996b4d5f2f8f5929ad701)
This commit is contained in:
Jessica McKellar
2013-11-25 10:47:19 -05:00
parent 1a9438ec70
commit dbc1b4b501
7 changed files with 75 additions and 2 deletions

View File

@@ -28,6 +28,10 @@ Please do not reply to this automated message. To respond to the missed messages
Cheers,
The Zulip Team
Note: click here to open your Zulip Settings page and disable future email notifications:
Manage email preferences:
https://{{ external_host }}/#settings
Unsubscribe from missed message emails:
{{ unsubscribe_link }}

View File

@@ -37,4 +37,4 @@ While you were away you received {{ message_count }} new message{{ message_count
<br>
The Zulip Team</p>
<p>Note: click <a href="https://{{ external_host }}/#settings">here</a> to open your Zulip Settings page and disable future email notifications</p>
<p><a href="https://{{ external_host }}/#settings">Manage email preferences</a> | <a href="{{ unsubscribe_link }}">Unsubscribe from missed message emails</a></p>

View File

@@ -0,0 +1,12 @@
{% extends "zerver/portico.html" %}
{% block portico_content %}
<h1>Unknown email unsubscribe request</h1>
<p>Hi there! It looks like you tried to unsubscribe from something, but we don't
recognize the URL.</p>
<p>Please double-check that you have the full URL and try again, or <a href="mailto:{{ zulip_admin }}?Subject=Unsubscribe%20me%2C%20please!&Body=Hi%20there!%0A%0AI%20clicked%20this%20unsubscribe%20link%20in%20a%20Zulip%20e-mail%2C%20but%20it%20took%20me%20to%20an%20error%20page%3A%0A%0A_____________%0A%0APlease%20unsubscribe%20me.%0A%0AThanks%2C%0A_____________%0A">email us</a> and we'll get this squared away!</p>
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends "zerver/portico.html" %}
{% block portico_content %}
<h1>Email settings updated</h1>
<p>We've updated your email subscription settings, and you won't get emails
about {{ subscription_type }} anymore.</p>
<p>To undo this change or review your other subscription settings, please visit your <a href="https://{{ external_host }}/#settings">Zulip Settings page</a>.</p>
{% endblock %}

View File

@@ -1920,6 +1920,21 @@ def build_message_list(user_profile, messages):
return messages_to_render
def unsubscribe_token(user_profile):
# Leverage the Django confirmations framework to generate and track unique
# unsubscription tokens.
return Confirmation.objects.get_link_for_object(user_profile).split("/")[-1]
def one_click_unsubscribe_link(user_profile, endpoint):
"""
Generate a unique link that a logged-out user can visit to unsubscribe from
Zulip e-mails without having to first log in.
"""
token = unsubscribe_token(user_profile)
base_url = "https://" + settings.EXTERNAL_HOST
resource_path = "accounts/unsubscribe/%s/%s" % (endpoint, token)
return "%s/%s" % (base_url.rstrip("/"), resource_path)
@statsd_increment("missed_message_reminders")
def do_send_missedmessage_events(user_profile, missed_messages):
"""
@@ -1960,6 +1975,11 @@ def do_send_missedmessage_events(user_profile, missed_messages):
template_payload['reply_warning'] = True
headers['Reply-To'] = "Nobody <%s>" % (settings.NOREPLY_EMAIL_ADDRESS,)
# Give users a one-click unsubscribe link they can use to stop getting
# missed message emails without having to log in first.
unsubscribe_link = one_click_unsubscribe_link(user_profile, "missed_messages")
template_payload["unsubscribe_link"] = unsubscribe_link
subject = "Missed Zulip%s from %s" % (plural_messages, sender_str)
from_email = "%s (via Zulip) <%s>" % (sender_str, settings.NOREPLY_EMAIL_ADDRESS)

View File

@@ -2325,3 +2325,23 @@ def remove_apns_device_token(request, user_profile, token=REQ):
def generate_204(request):
return HttpResponse(content=None, status=204)
def process_missedmessages_unsubscribe(token):
try:
confirmation = Confirmation.objects.get(confirmation_key=token)
except Confirmation.DoesNotExist:
return render_to_response('zerver/unsubscribe_link_error.html')
user_profile = confirmation.content_object
do_change_enable_offline_email_notifications(user_profile, False)
return render_to_response('zerver/unsubscribe_success.html',
{"subscription_type": "missed messages",
"external_host": settings.EXTERNAL_HOST})
# Login NOT required. These are for one-click unsubscribes.
def email_unsubscribe(request, type, token):
if type == "missed_messages":
return process_missedmessages_unsubscribe(token)
return render_to_response('zerver/unsubscribe_link_error.html', {},
context_instance=RequestContext(request))

View File

@@ -56,6 +56,11 @@ urlpatterns = patterns('',
url(r'^accounts/do_confirm/(?P<confirmation_key>[\w]+)', 'confirmation.views.confirm'),
url(r'^invite/$', 'zerver.views.initial_invite_page', name='initial-invite-users'),
# Unsubscription endpoint. Used for various types of e-mails (day 1 & 2,
# missed PMs, etc.)
url(r'^accounts/unsubscribe/(?P<type>[\w]+)/(?P<token>[\w]+)',
'zerver.views.email_unsubscribe'),
# Portico-styled page used to provide email confirmation of terms acceptance.
url(r'^accounts/accept_terms/$', 'zerver.views.accounts_accept_terms'),