diff --git a/templates/zerver/test_emails.html b/templates/zerver/test_emails.html
new file mode 100644
index 0000000000..6da6f00be3
--- /dev/null
+++ b/templates/zerver/test_emails.html
@@ -0,0 +1,21 @@
+{% extends "zerver/base.html" %}
+
+{% block content %}
+
+ {% for email in emails %}
+
Test for {{email.template}}
+ {% if email.failed %}
+
Email failed to render: {{ email.reason }}
+ {% else %}
+
Subject: {{email.subject}}
+ {% if email.text %}
+
{{ email.body }}
+ {% else %}
+ {% autoescape off %}
+ {{ email.body }}
+ {% endautoescape %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+
+{% endblock %}
diff --git a/tools/check-templates b/tools/check-templates
index a30b32e40c..5461fcaf82 100755
--- a/tools/check-templates
+++ b/tools/check-templates
@@ -150,6 +150,7 @@ def check_html_templates(templates, all_dups):
'templates/zerver/markdown_help.html',
'templates/zerver/navbar.html',
'templates/zerver/register.html',
+ 'templates/zerver/test_emails.html',
'zerver/webhooks/deskdotcom/doc.html',
'zerver/webhooks/librato/doc.html',
'zerver/webhooks/splunk/doc.html',
diff --git a/zerver/views/test_emails.py b/zerver/views/test_emails.py
new file mode 100755
index 0000000000..d1c9df2bda
--- /dev/null
+++ b/zerver/views/test_emails.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+from __future__ import absolute_import
+from __future__ import print_function
+import os
+from typing import List, Dict, Any
+from django.http import HttpRequest, HttpResponse
+from django.shortcuts import render
+from django.template import loader, TemplateDoesNotExist
+
+ZULIP_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../')
+
+def email_page(request):
+ # type: (HttpRequest) -> HttpResponse
+ # write fake data for all variables
+ test_context = {
+ 'user_profile': {
+ 'full_name': 'Zooly Zulipson',
+ 'email': 'zooly@zulip.org',
+ 'realm': {
+ 'uri': 'https://chat.zulip.org',
+ 'name': 'Zulip Community',
+ },
+ },
+ 'realm': {
+ 'uri': 'https://chat.zulip.org',
+ 'name': 'Zulip Community',
+ },
+ 'device_info': {
+ 'login_time': "12/12/12, 12:12:12",
+ 'device_browser': "Firefox",
+ 'device_os': "ZulipOS",
+ 'device_ip': '127.0.0.1',
+ },
+ 'referrer': {
+ 'full_name': 'Zooly Zulipson',
+ 'email': 'zooly@zulip.org',
+ },
+ 'user': {
+ 'full_name': 'Zooly Zulipson',
+ 'email': 'zooly@zulip.org',
+ },
+ 'referrer_name': 'Zooly Zulipson',
+ 'referrer_email': 'Zooly Zulipson',
+ 'realm_uri': 'https://chat.zulip.org',
+ 'server_uri': 'https://chat.zulip.org',
+ 'old_email': 'oldmail@zulip.org',
+ 'new_email': 'newmail@zulip.org',
+ 'activate_url': 'https://test.zulip.org',
+ 'support_email': 'admin@zulip.org',
+ 'zulip_support': 'admin@zulip.org',
+ 'unsubscribe_link': 'https://unsub.zulip.org',
+ }
+
+ # Do not render these templates,
+ # as they are currently unsupported
+ ignore = [
+ 'digest',
+ 'missed_message',
+ 'password_reset',
+ ]
+
+ files = os.listdir(os.path.join(ZULIP_PATH, 'templates', 'zerver', 'emails'))
+ templates = [] # type: List[str]
+ data = [] # type: List[Dict[str, Any]]
+
+ for f in files:
+ template = f.split('.')[0]
+ if template not in templates and template not in ignore:
+ templates.append(template)
+ try:
+ data.append(render_email(template, test_context))
+ except Exception as e:
+ data.append({'template': template, 'failed': True, 'reason': e})
+ return render(request, 'zerver/test_emails.html', {'emails': data})
+
+def render_email(template_prefix, context):
+ # type: (str, Dict[str, Any]) -> Dict[str, Any]
+ email = {} # type: Dict[str, Any]
+ email['template'] = template_prefix
+ email['subject'] = loader.render_to_string('zerver/emails/' + template_prefix + '.subject', context).strip()
+ message = loader.render_to_string('zerver/emails/' + template_prefix + '.txt', context)
+
+ try:
+ html_message = loader.render_to_string('/zerver/emails/' + template_prefix + '.html', context)
+ except TemplateDoesNotExist:
+ html_message = None
+
+ if html_message is not None:
+ email['body'] = html_message
+ email['text'] = False
+ else:
+ email['body'] = message
+ email['text'] = True
+
+ return email
diff --git a/zproject/dev_urls.py b/zproject/dev_urls.py
index 86021f8a86..66e6ffe984 100644
--- a/zproject/dev_urls.py
+++ b/zproject/dev_urls.py
@@ -4,6 +4,7 @@ import os.path
from django.views.static import serve
import zerver.views.registration
import zerver.views.auth
+import zerver.views.test_emails
# These URLs are available only in the development environment
@@ -30,6 +31,9 @@ urls = [
# The special no-password login endpoint for development
url(r'^devlogin/$', zerver.views.auth.login_page,
{'template_name': 'zerver/dev_login.html'}, name='zerver.views.auth.login_page'),
+
+ # Page for testing email templates
+ url(r'^emails/$', zerver.views.test_emails.email_page),
]
i18n_urls = [