mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2025-01-24 07:58:08 +00:00
Adds email config admin view (#2494)
This view lets you see your email configuration and send a test email.
This commit is contained in:
parent
ac8b060d58
commit
c314c9b5e3
11 changed files with 250 additions and 23 deletions
|
@ -18,6 +18,12 @@ def email_data():
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_email(user):
|
||||||
|
"""Just an admin checking if emails are sending"""
|
||||||
|
data = email_data()
|
||||||
|
send_email(user.email, *format_email("test", data))
|
||||||
|
|
||||||
|
|
||||||
def email_confirmation_email(user):
|
def email_confirmation_email(user):
|
||||||
"""newly registered users confirm email address"""
|
"""newly registered users confirm email address"""
|
||||||
data = email_data()
|
data = email_data()
|
||||||
|
|
12
bookwyrm/templates/email/test/html_content.html
Normal file
12
bookwyrm/templates/email/test/html_content.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{% extends 'email/html_layout.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
This is a test email.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
4
bookwyrm/templates/email/test/subject.html
Normal file
4
bookwyrm/templates/email/test/subject.html
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{% load i18n %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
Test email
|
||||||
|
{% endblocktrans %}
|
9
bookwyrm/templates/email/test/text_content.html
Normal file
9
bookwyrm/templates/email/test/text_content.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends 'email/text_layout.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block content %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
This is a test email.
|
||||||
|
{% endblocktrans %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
96
bookwyrm/templates/settings/email_config.html
Normal file
96
bookwyrm/templates/settings/email_config.html
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{% extends 'settings/layout.html' %}
|
||||||
|
{% load humanize %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load celery_tags %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Email Configuration" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block header %}{% trans "Email Configuration" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block panel %}
|
||||||
|
|
||||||
|
{% if error %}
|
||||||
|
<div class="notification is-danger is-light">
|
||||||
|
<span class="icon icon-x" aria-hidden="true"></span>
|
||||||
|
<span>
|
||||||
|
{% trans "Error sending test email:" %}
|
||||||
|
{{ error }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% elif success %}
|
||||||
|
<div class="notification is-success is-light">
|
||||||
|
<span class="icon icon-check" aria-hidden="true"></span>
|
||||||
|
<span>
|
||||||
|
{% trans "Successfully sent test email." %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<section class="block content">
|
||||||
|
<dl>
|
||||||
|
<dt class="is-pulled-left mr-5 has-text-weight-bold">
|
||||||
|
{% trans "Email sender:" %}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
{{ email_sender }}
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt class="is-pulled-left mr-5 has-text-weight-bold">
|
||||||
|
{% trans "Email backend:" %}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<code>{{ email_backend }}</code>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt class="is-pulled-left mr-5 has-text-weight-bold">
|
||||||
|
{% trans "Host:" %}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<code>{{ email_host }}</code>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt class="is-pulled-left mr-5 has-text-weight-bold">
|
||||||
|
{% trans "Host user:" %}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<code>{% firstof email_host_user "-" %}</code>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt class="is-pulled-left mr-5 has-text-weight-bold">
|
||||||
|
{% trans "Port:" %}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<code>{{ email_port }}</code>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt class="is-pulled-left mr-5 has-text-weight-bold">
|
||||||
|
{% trans "Use TLS:" %}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
{{ email_use_tls|yesno }}
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt class="is-pulled-left mr-5 has-text-weight-bold">
|
||||||
|
{% trans "Use SSL:" %}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
{{ email_use_ssl|yesno }}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</section>
|
||||||
|
<section class="block content box">
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed with email=request.user.email %}
|
||||||
|
Send test email to {{ email }}
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
<form action="{% url 'settings-email-config' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button type="submit" class="button is-success">
|
||||||
|
{% trans "Send test email" %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -81,12 +81,14 @@
|
||||||
{% url 'settings-imports' as url %}
|
{% url 'settings-imports' as url %}
|
||||||
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Imports" %}</a>
|
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Imports" %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
|
||||||
<ul class="menu-list">
|
|
||||||
<li>
|
<li>
|
||||||
{% url 'settings-celery' as url %}
|
{% url 'settings-celery' as url %}
|
||||||
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Celery status" %}</a>
|
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Celery status" %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
{% url 'settings-email-config' as url %}
|
||||||
|
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Email Configuration" %}</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.bookwyrm.edit_instance_settings %}
|
{% if perms.bookwyrm.edit_instance_settings %}
|
||||||
|
|
46
bookwyrm/tests/views/admin/test_email_config.py
Normal file
46
bookwyrm/tests/views/admin/test_email_config.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
""" test for app action functionality """
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.contrib.auth.models import Group
|
||||||
|
from django.template.response import TemplateResponse
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.test.client import RequestFactory
|
||||||
|
|
||||||
|
from bookwyrm import models, views
|
||||||
|
from bookwyrm.management.commands import initdb
|
||||||
|
from bookwyrm.tests.validate_html import validate_html
|
||||||
|
|
||||||
|
|
||||||
|
class EmailConfigViews(TestCase):
|
||||||
|
"""every response to a get request, html or json"""
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name
|
||||||
|
def setUp(self):
|
||||||
|
"""we need basic test data and mocks"""
|
||||||
|
self.factory = RequestFactory()
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.local_user = models.User.objects.create_user(
|
||||||
|
"mouse@local.com",
|
||||||
|
"mouse@mouse.mouse",
|
||||||
|
"password",
|
||||||
|
local=True,
|
||||||
|
localname="mouse",
|
||||||
|
)
|
||||||
|
initdb.init_groups()
|
||||||
|
initdb.init_permissions()
|
||||||
|
group = Group.objects.get(name="admin")
|
||||||
|
self.local_user.groups.set([group])
|
||||||
|
models.SiteSettings.objects.create()
|
||||||
|
|
||||||
|
def test_email_config_get(self):
|
||||||
|
"""there are so many views, this just makes sure it LOADS"""
|
||||||
|
view = views.EmailConfig.as_view()
|
||||||
|
request = self.factory.get("")
|
||||||
|
request.user = self.local_user
|
||||||
|
|
||||||
|
result = view(request)
|
||||||
|
self.assertIsInstance(result, TemplateResponse)
|
||||||
|
validate_html(result.render())
|
||||||
|
self.assertEqual(result.status_code, 200)
|
|
@ -119,7 +119,7 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
re_path(
|
re_path(
|
||||||
r"^settings/email-preview/?$",
|
r"^settings/email-preview/?$",
|
||||||
views.admin.site.email_preview,
|
views.admin.email_config.email_preview,
|
||||||
name="settings-email-preview",
|
name="settings-email-preview",
|
||||||
),
|
),
|
||||||
re_path(
|
re_path(
|
||||||
|
@ -314,6 +314,11 @@ urlpatterns = [
|
||||||
re_path(
|
re_path(
|
||||||
r"^settings/celery/?$", views.CeleryStatus.as_view(), name="settings-celery"
|
r"^settings/celery/?$", views.CeleryStatus.as_view(), name="settings-celery"
|
||||||
),
|
),
|
||||||
|
re_path(
|
||||||
|
r"^settings/email-config/?$",
|
||||||
|
views.EmailConfig.as_view(),
|
||||||
|
name="settings-email-config",
|
||||||
|
),
|
||||||
# landing pages
|
# landing pages
|
||||||
re_path(r"^about/?$", views.about, name="about"),
|
re_path(r"^about/?$", views.about, name="about"),
|
||||||
re_path(r"^privacy/?$", views.privacy, name="privacy"),
|
re_path(r"^privacy/?$", views.privacy, name="privacy"),
|
||||||
|
|
|
@ -10,6 +10,7 @@ from .admin.federation import Federation, FederatedServer
|
||||||
from .admin.federation import AddFederatedServer, ImportServerBlocklist
|
from .admin.federation import AddFederatedServer, ImportServerBlocklist
|
||||||
from .admin.federation import block_server, unblock_server, refresh_server
|
from .admin.federation import block_server, unblock_server, refresh_server
|
||||||
from .admin.email_blocklist import EmailBlocklist
|
from .admin.email_blocklist import EmailBlocklist
|
||||||
|
from .admin.email_config import EmailConfig
|
||||||
from .admin.imports import ImportList, disable_imports, enable_imports
|
from .admin.imports import ImportList, disable_imports, enable_imports
|
||||||
from .admin.ip_blocklist import IPBlocklist
|
from .admin.ip_blocklist import IPBlocklist
|
||||||
from .admin.invite import ManageInvites, Invite, InviteRequest
|
from .admin.invite import ManageInvites, Invite, InviteRequest
|
||||||
|
|
65
bookwyrm/views/admin/email_config.py
Normal file
65
bookwyrm/views/admin/email_config.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
""" is your email running? """
|
||||||
|
from django.contrib.auth.decorators import login_required, permission_required
|
||||||
|
from django.template.response import TemplateResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from bookwyrm import emailing
|
||||||
|
from bookwyrm import settings
|
||||||
|
|
||||||
|
# pylint: disable= no-self-use
|
||||||
|
@method_decorator(login_required, name="dispatch")
|
||||||
|
@method_decorator(
|
||||||
|
permission_required("bookwyrm.edit_instance_settings", raise_exception=True),
|
||||||
|
name="dispatch",
|
||||||
|
)
|
||||||
|
class EmailConfig(View):
|
||||||
|
"""View and test your emailing setup"""
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
"""View email config"""
|
||||||
|
data = view_data()
|
||||||
|
# TODO: show email previews
|
||||||
|
return TemplateResponse(request, "settings/email_config.html", data)
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
"""Send test email"""
|
||||||
|
data = view_data()
|
||||||
|
try:
|
||||||
|
emailing.test_email(request.user)
|
||||||
|
data["success"] = True
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
data["error"] = err
|
||||||
|
return TemplateResponse(request, "settings/email_config.html", data)
|
||||||
|
|
||||||
|
|
||||||
|
def view_data():
|
||||||
|
"""helper to get data for view"""
|
||||||
|
return {
|
||||||
|
"email_backend": settings.EMAIL_BACKEND,
|
||||||
|
"email_host": settings.EMAIL_HOST,
|
||||||
|
"email_port": settings.EMAIL_PORT,
|
||||||
|
"Email_host_user": settings.EMAIL_HOST_USER,
|
||||||
|
"email_use_tls": settings.EMAIL_USE_TLS,
|
||||||
|
"email_use_ssl": settings.EMAIL_USE_SSL,
|
||||||
|
"email_sender": settings.EMAIL_SENDER,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
|
||||||
|
def email_preview(request):
|
||||||
|
"""for development, renders and example email template"""
|
||||||
|
template = request.GET.get("email")
|
||||||
|
data = emailing.email_data()
|
||||||
|
data["subject_path"] = f"email/{template}/subject.html"
|
||||||
|
data["html_content_path"] = f"email/{template}/html_content.html"
|
||||||
|
data["text_content_path"] = f"email/{template}/text_content.html"
|
||||||
|
data["reset_link"] = "https://example.com/link"
|
||||||
|
data["invite_link"] = "https://example.com/link"
|
||||||
|
data["confirmation_link"] = "https://example.com/link"
|
||||||
|
data["confirmation_code"] = "AKJHKDGKJSDFG"
|
||||||
|
data["reporter"] = "ConcernedUser"
|
||||||
|
data["reportee"] = "UserName"
|
||||||
|
data["report_link"] = "https://example.com/link"
|
||||||
|
return TemplateResponse(request, "email/preview.html", data)
|
|
@ -4,7 +4,7 @@ from django.template.response import TemplateResponse
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views import View
|
from django.views import View
|
||||||
|
|
||||||
from bookwyrm import emailing, forms, models
|
from bookwyrm import forms, models
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable= no-self-use
|
# pylint: disable= no-self-use
|
||||||
|
@ -33,22 +33,3 @@ class Site(View):
|
||||||
|
|
||||||
data = {"site_form": forms.SiteForm(instance=site), "success": True}
|
data = {"site_form": forms.SiteForm(instance=site), "success": True}
|
||||||
return TemplateResponse(request, "settings/site.html", data)
|
return TemplateResponse(request, "settings/site.html", data)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
|
|
||||||
def email_preview(request):
|
|
||||||
"""for development, renders and example email template"""
|
|
||||||
template = request.GET.get("email")
|
|
||||||
data = emailing.email_data()
|
|
||||||
data["subject_path"] = f"email/{template}/subject.html"
|
|
||||||
data["html_content_path"] = f"email/{template}/html_content.html"
|
|
||||||
data["text_content_path"] = f"email/{template}/text_content.html"
|
|
||||||
data["reset_link"] = "https://example.com/link"
|
|
||||||
data["invite_link"] = "https://example.com/link"
|
|
||||||
data["confirmation_link"] = "https://example.com/link"
|
|
||||||
data["confirmation_code"] = "AKJHKDGKJSDFG"
|
|
||||||
data["reporter"] = "ConcernedUser"
|
|
||||||
data["reportee"] = "UserName"
|
|
||||||
data["report_link"] = "https://example.com/link"
|
|
||||||
return TemplateResponse(request, "email/preview.html", data)
|
|
||||||
|
|
Loading…
Reference in a new issue