Просмотр исходного кода

Merge pull request #1037 from rafalp/misago-site-url

Add MISAGO_ADDRESS setting
Rafał Pitoń 7 лет назад
Родитель
Сommit
56a13ace0c
41 измененных файлов с 331 добавлено и 127 удалено
  1. 67 0
      misago/admin/tests/test_admin_index.py
  2. 0 8
      misago/admin/tests/test_admin_views.py
  3. 13 0
      misago/admin/views/index.py
  4. 5 0
      misago/conf/defaults.py
  5. 25 11
      misago/core/mail.py
  6. 19 0
      misago/core/templatetags/misago_absoluteurl.py
  7. 0 2
      misago/core/testproject/urls.py
  8. 1 20
      misago/core/testproject/views.py
  9. 8 9
      misago/core/tests/test_mail.py
  10. 27 1
      misago/core/tests/test_templatetags.py
  11. 33 1
      misago/core/tests/test_utils.py
  12. 19 0
      misago/core/utils.py
  13. 8 0
      misago/project_template/project_name/settings.py
  14. 29 2
      misago/templates/misago/admin/index.html
  15. 3 3
      misago/templates/misago/emails/activation/by_admin.html
  16. 3 3
      misago/templates/misago/emails/activation/by_admin.txt
  17. 3 3
      misago/templates/misago/emails/activation/by_user.html
  18. 3 3
      misago/templates/misago/emails/activation/by_user.txt
  19. 2 1
      misago/templates/misago/emails/base.html
  20. 3 3
      misago/templates/misago/emails/change_email.html
  21. 3 3
      misago/templates/misago/emails/change_email.txt
  22. 3 3
      misago/templates/misago/emails/change_password.html
  23. 3 3
      misago/templates/misago/emails/change_password.txt
  24. 3 3
      misago/templates/misago/emails/change_password_form_link.html
  25. 3 3
      misago/templates/misago/emails/change_password_form_link.txt
  26. 3 3
      misago/templates/misago/emails/privatethread/added.html
  27. 3 3
      misago/templates/misago/emails/privatethread/added.txt
  28. 3 3
      misago/templates/misago/emails/register/complete.html
  29. 3 3
      misago/templates/misago/emails/register/complete.txt
  30. 3 3
      misago/templates/misago/emails/register/inactive.html
  31. 4 4
      misago/templates/misago/emails/register/inactive.txt
  32. 5 5
      misago/templates/misago/emails/thread/reply.html
  33. 4 4
      misago/templates/misago/emails/thread/reply.txt
  34. 2 2
      misago/threads/api/postingendpoint/emailnotification.py
  35. 2 3
      misago/threads/participants.py
  36. 2 4
      misago/users/api/auth.py
  37. 1 1
      misago/users/api/userendpoints/changeemail.py
  38. 2 1
      misago/users/api/userendpoints/changepassword.py
  39. 5 2
      misago/users/registration.py
  40. 1 1
      misago/users/views/admin/users.py
  41. 2 0
      runtests.py

+ 67 - 0
misago/admin/tests/test_admin_index.py

@@ -0,0 +1,67 @@
+from django.test import TestCase, override_settings
+from django.urls import reverse
+
+from misago.admin.testutils import AdminTestCase
+from misago.admin.views.index import check_misago_address
+
+
+class AdminIndexViewTests(AdminTestCase):
+    def test_view_returns_200(self):
+        """admin index view returns 200"""
+        response = self.client.get(reverse('misago:admin:index'))
+
+        self.assertContains(response, self.user.username)
+
+    def test_view_contains_address_check(self):
+        """admin index view contains address check"""
+        response = self.client.get(reverse('misago:admin:index'))
+
+        self.assertContains(response, "MISAGO_ADDRESS")
+
+
+class RequestMock(object):
+    absolute_uri = 'https://misago-project.org/somewhere/'
+
+    def build_absolute_uri(self, location):
+        assert location == '/'
+        return self.absolute_uri
+
+
+request = RequestMock()
+incorrect_address = 'http://somewhere.com'
+correct_address = request.absolute_uri
+
+
+class AdminIndexAddressCheckTests(TestCase):
+    @override_settings(MISAGO_ADDRESS=None)
+    def test_address_not_set(self):
+        """check handles address not set"""
+        result = check_misago_address(request)
+
+        self.assertEqual(result, {
+            'is_correct': False,
+            'set_address': None,
+            'correct_address': request.absolute_uri,
+        })
+
+    @override_settings(MISAGO_ADDRESS=incorrect_address)
+    def test_address_set_invalid(self):
+        """check handles incorrect address"""
+        result = check_misago_address(request)
+
+        self.assertEqual(result, {
+            'is_correct': False,
+            'set_address': incorrect_address,
+            'correct_address': request.absolute_uri,
+        })
+
+    @override_settings(MISAGO_ADDRESS=correct_address)
+    def test_address_set_valid(self):
+        """check handles correct address"""
+        result = check_misago_address(request)
+
+        self.assertEqual(result, {
+            'is_correct': True,
+            'set_address': correct_address,
+            'correct_address': request.absolute_uri,
+        })

+ 0 - 8
misago/admin/tests/test_admin_views.py

@@ -196,14 +196,6 @@ class AdminViewAccessTests(AdminTestCase):
         self.assertContains(response, self.user.username)
 
 
-class AdminIndexViewTests(AdminTestCase):
-    def test_view_returns_200(self):
-        """admin index view returns 200"""
-        response = self.client.get(reverse('misago:admin:index'))
-
-        self.assertContains(response, self.user.username)
-
-
 class Admin404ErrorTests(AdminTestCase):
     def test_list_search_unicode_handling(self):
         """querystring creation handles unicode strings"""

+ 13 - 0
misago/admin/views/index.py

@@ -12,6 +12,7 @@ from django.http import Http404, JsonResponse
 from django.utils.translation import ugettext as _
 
 from misago import __version__
+from misago.conf import settings
 from misago.core.cache import cache
 from misago.threads.models import Post, Thread
 
@@ -38,6 +39,7 @@ def admin_index(request):
     return render(
         request, 'misago/admin/index.html', {
             'db_stats': db_stats,
+            'address_check': check_misago_address(request),
 
             'allow_version_check': ALLOW_VERSION_CHECK,
             'version_check': cache.get(VERSION_CHECK_CACHE_KEY),
@@ -45,6 +47,17 @@ def admin_index(request):
     )
 
 
+def check_misago_address(request):
+    set_address = settings.MISAGO_ADDRESS
+    correct_address = request.build_absolute_uri('/')
+
+    return {
+        'is_correct': set_address == correct_address,
+        'set_address': set_address,
+        'correct_address': correct_address,
+    }
+
+
 def check_version(request):
     if not ALLOW_VERSION_CHECK or request.method != "POST":
         raise Http404()

+ 5 - 0
misago/conf/defaults.py

@@ -7,6 +7,11 @@ instead of Django's `django.conf.settings`.
 """
 
 
+# Complete HTTP address of your Misago installation
+
+MISAGO_ADDRESS = None
+
+
 # Permissions system extensions
 # https://misago.readthedocs.io/en/latest/developers/acls.html#extending-permissions-system
 

+ 25 - 11
misago/core/mail.py

@@ -1,15 +1,29 @@
 from django.core import mail as djmail
 from django.template.loader import render_to_string
+from django.utils.translation import get_language
 
+from misago.conf import db_settings, settings
 
-def build_mail(request, recipient, subject, template, context=None):
-    context = context or {}
-    context['sender'] = request.user
-    context['recipient'] = recipient
-    context['subject'] = subject
+from .utils import get_host_from_address
 
-    message_plain = render_to_string('%s.txt' % template, context, request=request)
-    message_html = render_to_string('%s.html' % template, context, request=request)
+
+def build_mail(recipient, subject, template, sender=None, context=None):
+    context = context.copy() if context else {}
+    context.update({
+        'SITE_ADDRESS': settings.MISAGO_ADDRESS,
+        'SITE_HOST': get_host_from_address(settings.MISAGO_ADDRESS),
+        'LANGUAGE_CODE': get_language()[:2],
+        'LOGIN_URL': settings.LOGIN_URL,
+
+        'misago_settings': db_settings,
+
+        'user': recipient,
+        'sender': sender,
+        'subject': subject,
+    })
+
+    message_plain = render_to_string('%s.txt' % template, context)
+    message_html = render_to_string('%s.html' % template, context)
 
     message = djmail.EmailMultiAlternatives(subject, message_plain, to=[recipient.email])
     message.attach_alternative(message_html, "text/html")
@@ -17,16 +31,16 @@ def build_mail(request, recipient, subject, template, context=None):
     return message
 
 
-def mail_user(request, recipient, subject, template, context=None):
-    message = build_mail(request, recipient, subject, template, context)
+def mail_user(recipient, subject, template, sender=None, context=None):
+    message = build_mail(recipient, subject, template, sender, context)
     message.send()
 
 
-def mail_users(request, recipients, subject, template, context=None):
+def mail_users(recipients, subject, template, sender=None, context=None):
     messages = []
 
     for recipient in recipients:
-        messages.append(build_mail(request, recipient, subject, template, context))
+        messages.append(build_mail(recipient, subject, template, sender, context))
 
     if messages:
         send_messages(messages)

+ 19 - 0
misago/core/templatetags/misago_absoluteurl.py

@@ -0,0 +1,19 @@
+from django import template
+from django.urls import reverse
+
+from misago.conf import settings
+
+register = template.Library()
+
+
+@register.simple_tag
+def absoluteurl(url_or_name, *args, **kwargs):
+    if not settings.MISAGO_ADDRESS:
+        return None
+
+    absolute_url_prefix = settings.MISAGO_ADDRESS.rstrip('/')
+
+    if '/' not in url_or_name:
+        url_or_name = reverse(url_or_name, args=args, kwargs=kwargs)
+    
+    return u'{}{}'.format(absolute_url_prefix, url_or_name)

+ 0 - 2
misago/core/testproject/urls.py

@@ -29,8 +29,6 @@ urlpatterns = [
         ),
         name='django-i18n'
     ),
-    url(r'^forum/test-mail-user/$', views.test_mail_user, name='test-mail-user'),
-    url(r'^forum/test-mail-users/$', views.test_mail_users, name='test-mail-users'),
     url(r'^forum/test-pagination/$', views.test_pagination, name='test-pagination'),
     url(
         r'^forum/test-pagination/(?P<page>[1-9][0-9]*)/$',

+ 1 - 20
misago/core/testproject/views.py

@@ -1,12 +1,11 @@
 from rest_framework.decorators import api_view
 
-from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.http import Http404, HttpResponse
 from social_core.exceptions import AuthFailed, NotAllowedToDisconnect, WrongBackend
 from social_core.backends.github import GithubOAuth2
 
-from misago.core import errorpages, mail
+from misago.core import errorpages
 from misago.core.decorators import require_POST
 from misago.core.exceptions import Banned, SocialAuthBanned, SocialAuthFailed
 from misago.core.shortcuts import paginate, paginated_response, validate_slug
@@ -17,24 +16,6 @@ from .models import Model
 from .serializers import MockSerializer
 
 
-UserModel = get_user_model()
-
-
-def test_mail_user(request):
-    test_user = UserModel.objects.all().first()
-    mail.mail_user(request, test_user, "Misago Test Mail", "misago/emails/base")
-
-    return HttpResponse("Mailed user!")
-
-
-def test_mail_users(request):
-    mail.mail_users(
-        request, UserModel.objects.iterator(), "Misago Test Spam", "misago/emails/base"
-    )
-
-    return HttpResponse("Mailed users!")
-
-
 def test_pagination(request, page=None):
     items = range(15)
     page = paginate(items, page, 5)

+ 8 - 9
misago/core/tests/test_mailer.py → misago/core/tests/test_mail.py

@@ -1,20 +1,20 @@
 from django.contrib.auth import get_user_model
 from django.core import mail
-from django.test import TestCase, override_settings
+from django.test import TestCase
 from django.urls import reverse
 
+from misago.core.mail import mail_user, mail_users
+
 
 UserModel = get_user_model()
 
 
-@override_settings(ROOT_URLCONF='misago.core.testproject.urls')
-class MisagoMailerTests(TestCase):
+class MailTests(TestCase):
     def test_mail_user(self):
         """mail_user sets message in backend"""
         user = UserModel.objects.create_user('Bob', 'bob@bob.com', 'pass123')
 
-        response = self.client.get(reverse('test-mail-user'))
-        self.assertEqual(response.status_code, 200)
+        mail_user(user, "Misago Test Mail", "misago/emails/base")
 
         self.assertEqual(mail.outbox[0].subject, "Misago Test Mail")
 
@@ -26,16 +26,15 @@ class MisagoMailerTests(TestCase):
 
     def test_mail_users(self):
         """mail_users sets messages in backend"""
-        test_users = (
+        test_users = [
             UserModel.objects.create_user('Alpha', 'alpha@test.com', 'pass123'),
             UserModel.objects.create_user('Beta', 'beta@test.com', 'pass123'),
             UserModel.objects.create_user('Niner', 'niner@test.com', 'pass123'),
             UserModel.objects.create_user('Foxtrot', 'foxtrot@test.com', 'pass123'),
             UserModel.objects.create_user('Uniform', 'uniform@test.com', 'pass123'),
-        )
+        ]
 
-        response = self.client.get(reverse('test-mail-users'))
-        self.assertEqual(response.status_code, 200)
+        mail_users(test_users, "Misago Test Spam", "misago/emails/base")
 
         spams_sent = 0
         for message in mail.outbox:

+ 27 - 1
misago/core/tests/test_templatetags.py

@@ -1,8 +1,34 @@
 from django import forms
 from django.template import Context, Template, TemplateSyntaxError
-from django.test import TestCase
+from django.test import TestCase, override_settings
 
 from misago.core.templatetags import misago_batch
+from misago.core.templatetags.misago_absoluteurl import absoluteurl
+
+
+TEST_ADDRESS = 'https://testsite.com/'
+
+
+class AbsoluteUrlTests(TestCase):
+    @override_settings(MISAGO_ADDRESS=None)
+    def test_address_is_none(self):
+        """template tag returns null if address setting is not filled"""
+        result = absoluteurl('misago:index')
+        self.assertIsNone(result)
+
+    
+    @override_settings(MISAGO_ADDRESS=TEST_ADDRESS)
+    def test_prefix_url(self):
+        """template tag prefixes already reversed url"""
+        result = absoluteurl('/')
+        self.assertEqual(result, TEST_ADDRESS)
+
+    
+    @override_settings(MISAGO_ADDRESS=TEST_ADDRESS)
+    def test_rprefix_url_name(self):
+        """template tag reverses url name and prefixes it"""
+        result = absoluteurl('misago:index')
+        self.assertEqual(result, TEST_ADDRESS)
 
 
 class CaptureTests(TestCase):

+ 33 - 1
misago/core/tests/test_utils.py

@@ -9,7 +9,7 @@ from django.utils import six
 
 from misago.core.utils import (
     clean_return_path, format_plaintext_for_html, is_referer_local, is_request_to_misago,
-    parse_iso8601_string, slugify, get_exception_message, clean_ids_list)
+    parse_iso8601_string, slugify, get_exception_message, clean_ids_list, get_host_from_address)
 
 
 class IsRequestToMisagoTests(TestCase):
@@ -298,3 +298,35 @@ class CleanIdsListTests(TestCase):
         for invalid_input in INVALID_INPUTS:
             with self.assertRaisesMessage(PermissionDenied, "Test error message!"):
                 clean_ids_list(invalid_input, "Test error message!")
+
+
+class GetHostFromAddressTests(TestCase):
+    def test_none(self):
+        """get_host_from_address returns None for None"""
+        result = get_host_from_address(None)
+        self.assertIsNone(result)
+
+    def test_empty_string(self):
+        """get_host_from_address returns None for empty string"""
+        result = get_host_from_address('')
+        self.assertIsNone(result)
+
+    def test_hostname(self):
+        """get_host_from_address returns hostname unchanged"""
+        result = get_host_from_address('hostname')
+        self.assertEqual(result, 'hostname')
+        
+    def test_hostname_with_trailing_slash(self):
+        """get_host_from_address returns hostname for hostname with trailing slash"""
+        result = get_host_from_address('//hostname')
+        self.assertEqual(result, 'hostname')
+
+    def test_hostname_with_port(self):
+        """get_host_from_address returns hostname for hostname with port"""
+        result = get_host_from_address('hostname:8888')
+        self.assertEqual(result, 'hostname')
+        
+    def test_hostname_with_port_path_and_protocol(self):
+        """get_host_from_address returns hostname for hostname with port and path"""
+        result = get_host_from_address('https://hostname:8888/somewhere/else/')
+        self.assertEqual(result, 'hostname')

+ 19 - 0
misago/core/utils.py

@@ -154,3 +154,22 @@ def clean_ids_list(ids_list, error_message):
         return list(map(int, ids_list))
     except (ValueError, TypeError):
         raise PermissionDenied(error_message)
+
+
+def get_host_from_address(address):
+    if not address:
+        return None
+
+    if address.lower().startswith('https://'):
+        address = address[8:]
+    if address.lower().startswith('http://'):
+        address = address[7:]
+    if address[0] == '/':
+        address = address.lstrip('/')
+    if '/' in address:
+        address = address.split('/')[0] or address
+    if ':' in address:
+        address = address.split(':')[0] or address
+
+    return address
+    

+ 8 - 0
misago/project_template/project_name/settings.py

@@ -365,6 +365,14 @@ REST_FRAMEWORK = {
 # Misago specific settings
 # https://misago.readthedocs.io/en/latest/developers/settings.html
 
+# Complete HTTP address to your Misago site homepage. Misago relies on this address to create
+# links in e-mails that are sent to site users.
+# On Misago admin panel home page you will find a message telling you if you have entered the
+# correct value, or what value is correct in case you've didn't.
+
+MISAGO_ADDRESS = 'http://my-misago-site.com/'
+
+
 # PostgreSQL text search configuration to use in searches
 # Defaults to "simple", for list of installed configurations run "\dF" in "psql"
 # Standard configs as of PostgreSQL 9.5 are: dutch, english, finnish, french,

+ 29 - 2
misago/templates/misago/admin/index.html

@@ -1,5 +1,5 @@
 {% extends "misago/admin/base.html" %}
-{% load i18n %}
+{% load i18n misago_capture %}
 
 
 {% block title %}{% trans "Home" %} | {{ block.super }}{% endblock %}
@@ -19,7 +19,34 @@
   <div class="row">
     <div class="col-md-8">
 
-
+      <h2>{% trans "System checks" %}</h2>
+
+      {% if address_check.is_correct %}
+        <div class="alert alert-success" role="alert">
+          <p>{% trans "MISAGO_ADDRESS setting appears to be correct." %}</p>
+        </div>
+      {% elif address_check.set_address %}
+        <div class="alert alert-warning" role="alert">
+          <p class="lead">{% trans "The settings.py value for MISAGO_ADDRESS appears to be incorrect." %}</p>
+          <p>
+            {% capture trimmed as set_address %}
+              <code>{{ address_check.set_address }}</code>
+            {% endcapture %}
+            {% capture trimmed as correct_address %}
+              <code>{{ address_check.correct_address }}</code>
+            {% endcapture %}
+            {% blocktrans trimmed with configured_address=set_address|safe correct_address=correct_address|safe %}
+              Your MISAGO_ADDRESS is set to {{ configured_address }} while correct value appears to be {{ correct_address }}.
+            {% endblocktrans %}
+          </p>
+          <p>{% trans "Misago uses this setting to build correct links in e-mails sent to site users." %}</p>
+        </div>
+      {% else %}
+        <div class="alert alert-danger" role="alert">
+          <p class="lead">{% trans "The settings.py is missing MISAGO_ADDRESS value." %}</p>
+          <p>{% trans "Misago uses this setting to build correct links in e-mails sent to site users." %}</p>
+        </div>
+      {% endif %}
 
     </div>
     <div class="col-md-4">

+ 3 - 3
misago/templates/misago/emails/activation/by_admin.html

@@ -1,15 +1,15 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n misago_capture %}
+{% load i18n misago_absoluteurl misago_capture %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, your account has been activated by forum administrator.
 {% endblocktrans %}
 <br>
 <br>
 {% capture trimmed as login_link %}
-<a href="{{ SITE_ADDRESS }}{% url LOGIN_URL %}">{% trans "this form" %}</a>
+<a href="{% absoluteurl LOGIN_URL %}">{% trans "this form" %}</a>
 {% endcapture %}
 {% blocktrans trimmed with login_form=login_link|safe %}
 You can now sign in to it using {{ login_form }}.

+ 3 - 3
misago/templates/misago/emails/activation/by_admin.txt

@@ -1,14 +1,14 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, your account has been activated by forum administrator.
 {% endblocktrans %}
 
 {% blocktrans trimmed %}
 You can now sign in to it using the form below:
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url LOGIN_URL %}
+{% absoluteurl LOGIN_URL %}
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/activation/by_user.html

@@ -1,13 +1,13 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n misago_capture %}
+{% load i18n misago_absoluteurl misago_capture %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, to activate your account click the below link:
 {% endblocktrans %}
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}">{% trans "Activate my account!" %}</a>
+<a href="{% absoluteurl 'misago:activate-by-token' pk=user.pk token=activation_token %}">{% trans "Activate my account!" %}</a>
 <br>
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/activation/by_user.txt

@@ -1,10 +1,10 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, to activate your account click the below link:
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}
+{% absoluteurl 'misago:activate-by-token' pk=user.pk token=activation_token %}
 {% endblock content %}

+ 2 - 1
misago/templates/misago/emails/base.html

@@ -1,3 +1,4 @@
+{% load misago_absoluteurl %}
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 <html lang="{{ LANGUAGE_CODE }}">
 <head>
@@ -55,7 +56,7 @@
               <table border="0" width="100%" height="100%" cellpadding="0" cellspacing="0">
                 <tr>
                   <td valign="middle" style="font-size: 28px; line-height: 24px; color: #555555;">{{ misago_settings.forum_name }}</td>
-                  <td align="center" valign="middle" width="30"><img src="{{ SITE_ADDRESS }}{% url 'misago:user-avatar' pk=recipient.pk size=32 %}" width="32" height="32" style="border-radius: 3px;" alt=""></td>
+                  <td align="center" valign="middle" width="30"><img src="{% absoluteurl 'misago:user-avatar' pk=user.pk size=32 %}" width="32" height="32" style="border-radius: 3px;" alt=""></td>
                 </tr>
               </table>
             <br>

+ 3 - 3
misago/templates/misago/emails/change_email.html

@@ -1,9 +1,9 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, you are receiving this message because you have changed your e-mail address.
 {% endblocktrans %}
 <br>
@@ -13,6 +13,6 @@ To confirm this change, click the link below:
 {% endblocktrans %}
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:options-confirm-email-change' token=token %}">{% trans "Save changes" %}</a>
+<a href="{% absoluteurl 'misago:options-confirm-email-change' token=token %}">{% trans "Save changes" %}</a>
 <br>
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/change_email.txt

@@ -1,14 +1,14 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, you are receiving this message because you have changed your e-mail address.
 {% endblocktrans %}
 
 {% blocktrans trimmed %}
 To confirm this change, click the link below:
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:options-confirm-email-change' token=token %}
+{% absoluteurl 'misago:options-confirm-email-change' token=token %}
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/change_password.html

@@ -1,9 +1,9 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, you are receiving this message because you have changed your password.
 {% endblocktrans %}
 <br>
@@ -13,6 +13,6 @@ To confirm this change, click the link below:
 {% endblocktrans %}
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:options-confirm-password-change' token=token %}">{% trans "Save changes" %}</a>
+<a href="{% absoluteurl 'misago:options-confirm-password-change' token=token %}">{% trans "Save changes" %}</a>
 <br>
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/change_password.txt

@@ -1,14 +1,14 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, you are receiving this message because you have changed your password.
 {% endblocktrans %}
 
 {% blocktrans trimmed %}
 To confirm this change, click the link below:
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:options-confirm-password-change' token=token %}
+{% absoluteurl 'misago:options-confirm-password-change' token=token %}
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/change_password_form_link.html

@@ -1,9 +1,9 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, you are receiving this message because you want to change forgotten password for your forum account.
 {% endblocktrans %}
 <br>
@@ -13,6 +13,6 @@ To change your account password click the link below:
 {% endblocktrans %}
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:forgotten-password-change-form' pk=recipient.pk token=confirmation_token %}">{% trans "Set new password" %}</a>
+<a href="{% absoluteurl 'misago:forgotten-password-change-form' pk=user.pk token=confirmation_token %}">{% trans "Set new password" %}</a>
 <br>
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/change_password_form_link.txt

@@ -1,14 +1,14 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, you are receiving this message because you want to change forgotten password for your forum account.
 {% endblocktrans %}
 
 {% blocktrans trimmed %}
 To change your account password click the link below:
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:forgotten-password-change-form' pk=recipient.pk token=confirmation_token %}
+{% absoluteurl 'misago:forgotten-password-change-form' pk=user.pk token=confirmation_token %}
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/privatethread/added.html

@@ -1,12 +1,12 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n misago_capture %}
+{% load i18n misago_absoluteurl misago_capture %}
 
 
 {% block content %}
 {% capture trimmed as thread_title %}
 <b>{{ thread.title }}</b>
 {% endcapture %}
-{% blocktrans trimmed with user=recipient.username sender=sender.username thread=thread_title|safe %}
+{% blocktrans trimmed with user=user.username sender=sender.username thread=thread_title|safe %}
 {{ user }}, you are receiving this message because {{ sender }} has invited you to participate in private thread {{ thread }}.
 {% endblocktrans %}
 <br>
@@ -16,6 +16,6 @@ To read this thread click the link below:
 {% endblocktrans %}
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{{ thread.get_absolute_url }}">{{ thread.title }}</a>
+<a href="{% absoluteurl thread.get_absolute_url %}">{{ thread.title }}</a>
 <br>
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/privatethread/added.txt

@@ -1,14 +1,14 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient.username sender=sender.username thread=thread.title %}
+{% blocktrans trimmed with user=user.username sender=sender.username thread=thread.title %}
 {{ user }}, you are receiving this message because {{ sender }} has invited you to participate in private thread "{{ thread }}".
 {% endblocktrans %}
 
 {% blocktrans trimmed %}
 To read this thread click the link below:
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{{ thread.get_absolute_url }}
+{% absoluteurl thread.get_absolute_url %}
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/register/complete.html

@@ -1,9 +1,9 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n misago_capture %}
+{% load i18n misago_absoluteurl misago_capture %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, thank you for joining us!
 {% endblocktrans %}
 <br>
@@ -15,7 +15,7 @@ You may now join discussion on our forums. Why not spend a minute or two to have
 <br>
 <br>
 {% capture trimmed as login_link %}
-<a href="{{ SITE_ADDRESS }}{% url LOGIN_URL %}">{% trans "this form" %}</a>
+<a href="{% absoluteurl LOGIN_URL %}">{% trans "this form" %}</a>
 {% endcapture %}
 {% blocktrans trimmed with login_form=login_link|safe %}
 You can always sign in to your account using {{ login_form }}.

+ 3 - 3
misago/templates/misago/emails/register/complete.txt

@@ -1,9 +1,9 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, thank you for joining us!
 {% endblocktrans %}
 
@@ -14,5 +14,5 @@ You may now join discussion on our forums. Why not spend a minute or two to have
 {% blocktrans trimmed %}
 You can always sign in to your account using the form below:
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url LOGIN_URL %}
+{% absoluteurl LOGIN_URL %}
 {% endblock content %}

+ 3 - 3
misago/templates/misago/emails/register/inactive.html

@@ -1,5 +1,5 @@
 {% extends "misago/emails/register/complete.html" %}
-{% load i18n misago_capture %}
+{% load i18n misago_absoluteurl misago_capture %}
 
 
 {% block activation-message %}
@@ -24,11 +24,11 @@
   {% endblocktrans %}
   <br>
   <br>
-  <a href="{{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}">{% trans "Activate my account!" %}</a>
+  <a href="{% absoluteurl 'misago:activate-by-token' pk=user.pk token=activation_token %}">{% trans "Activate my account!" %}</a>
   <br>
   <br>
   {% capture trimmed as login_link %}
-  <a href="{{ SITE_ADDRESS }}{% url LOGIN_URL %}">{% trans "this form" %}</a>
+  <a href="{% absoluteurl LOGIN_URL %}">{% trans "this form" %}</a>
   {% endcapture %}
   {% blocktrans trimmed with login_form=login_link|safe %}
   Once your account is activated, you can always sign in to it using {{ login_form }}.

+ 4 - 4
misago/templates/misago/emails/register/inactive.txt

@@ -1,9 +1,9 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient %}
+{% blocktrans trimmed with user=user %}
 {{ user }}, thank you for joining us!
 {% endblocktrans %}
 {% if activation_by_admin %}
@@ -25,11 +25,11 @@
   {% blocktrans trimmed %}
   Before you will be able to join discussion on our forums, you have to activate your account. To do so, simply click the link below:
   {% endblocktrans %}
-  {{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}"
+  {% absoluteurl 'misago:activate-by-token' pk=user.pk token=activation_token %}"
 
   {% blocktrans trimmed with login_form=login_link|safe %}
   Once your account is activated, you can always sign in to it using the form below:
   {% endblocktrans %}
-  {{ SITE_ADDRESS }}{% url LOGIN_URL %}
+  {% absoluteurl LOGIN_URL %}
 {% endif %}
 {% endblock content %}

+ 5 - 5
misago/templates/misago/emails/thread/reply.html

@@ -1,19 +1,19 @@
 {% extends "misago/emails/base.html" %}
-{% load i18n misago_capture %}
+{% load i18n misago_absoluteurl misago_capture %}
 
 
 {% block content %}
 {% capture trimmed as thread_link %}
-  <a href="{{ SITE_ADDRESS }}{{ thread.get_absolute_url }}">{{ thread }}</a>
+  <a href="{% absoluteurl thread.get_absolute_url %}">{{ thread }}</a>
 {% endcapture %}
-{% blocktrans trimmed with user=recipient poster=user thread=thread_link|safe %}
-{{ user }}, you are receiving this message because {{ poster }} has replied to the thread {{ thread }} that you are subscribed to.
+{% blocktrans trimmed with user=user sender=sender thread=thread_link|safe %}
+{{ user }}, you are receiving this message because {{ sender }} has replied to the thread {{ thread }} that you are subscribed to.
 {% endblocktrans %}
 <br>
 <br>
 {% trans "To read this reply, click the below link:" %}
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{{ post.get_absolute_url }}">{% trans "Go to reply" %}</a>
+<a href="{% absoluteurl post.get_absolute_url %}">{% trans "Go to reply" %}</a>
 <br>
 {% endblock content %}

+ 4 - 4
misago/templates/misago/emails/thread/reply.txt

@@ -1,12 +1,12 @@
 {% extends "misago/emails/base.txt" %}
-{% load i18n %}
+{% load i18n misago_absoluteurl %}
 
 
 {% block content %}
-{% blocktrans trimmed with user=recipient poster=user thread=thread %}
-{{ user }}, you are receiving this message because {{ poster }} has replied to the thread "{{ thread }}" that you are subscribed to.
+{% blocktrans trimmed with user=user sender=sender thread=thread %}
+{{ user }}, you are receiving this message because {{ sender }} has replied to the thread "{{ thread }}" that you are subscribed to.
 {% endblocktrans %}
 
 {% trans "To read this reply, click the below link:" %}
-{{ SITE_ADDRESS }}{{ post.get_absolute_url }}
+{% absoluteurl post.get_absolute_url %}
 {% endblock content %}

+ 2 - 2
misago/threads/api/postingendpoint/emailnotification.py

@@ -43,11 +43,11 @@ class EmailNotificationMiddleware(PostingMiddleware):
         subject_formats = {'user': self.user.username, 'thread': self.thread.title}
 
         return build_mail(
-            self.request,
             subscriber,
             subject % subject_formats,
             'misago/emails/thread/reply',
-            {
+            sender=self.user,
+            context={
                 'thread': self.thread,
                 'post': self.post,
             },

+ 2 - 3
misago/threads/participants.py

@@ -149,9 +149,8 @@ def build_noticiation_email(request, thread, user):
     }
 
     return build_mail(
-        request, user, subject % subject_formats, 'misago/emails/privatethread/added', {
-            'thread': thread,
-        }
+        user, subject % subject_formats, 'misago/emails/privatethread/added',
+        sender=request.user, context={'thread': thread}
     )
 
 

+ 2 - 4
misago/users/api/auth.py

@@ -103,11 +103,10 @@ def send_activation(request):
         }
 
         mail_user(
-            request,
             requesting_user,
             mail_subject,
             'misago/emails/activation/by_user',
-            {
+            context={
                 'activation_token': make_activation_token(requesting_user),
             },
         )
@@ -144,11 +143,10 @@ def send_password_form(request):
         confirmation_token = make_password_change_token(requesting_user)
 
         mail_user(
-            request,
             requesting_user,
             mail_subject,
             'misago/emails/change_password_form_link',
-            {
+            context={
                 'confirmation_token': confirmation_token,
             },
         )

+ 1 - 1
misago/users/api/userendpoints/changeemail.py

@@ -25,7 +25,7 @@ def change_email_endpoint(request, pk=None):
         request.user.email = serializer.validated_data['new_email']
 
         mail_user(
-            request, request.user, mail_subject, 'misago/emails/change_email', {'token': token}
+            request.user, mail_subject, 'misago/emails/change_email', context={'token': token}
         )
 
         message = _("E-mail change confirmation link was sent to new address.")

+ 2 - 1
misago/users/api/userendpoints/changepassword.py

@@ -24,7 +24,8 @@ def change_password_endpoint(request, pk=None):
         mail_subject = mail_subject % {'forum_name': settings.forum_name}
 
         mail_user(
-            request, request.user, mail_subject, 'misago/emails/change_password', {'token': token}
+            request.user, mail_subject, 'misago/emails/change_password',
+            context={'token': token}
         )
 
         return Response({

+ 5 - 2
misago/users/registration.py

@@ -16,14 +16,17 @@ def send_welcome_email(request, user):
         activation_by_user = user.requires_activation_by_user
 
         mail_user(
-            request, user, mail_subject, 'misago/emails/register/inactive', {
+            user,
+            mail_subject,
+            'misago/emails/register/inactive',
+            context={
                 'activation_token': activation_token,
                 'activation_by_admin': activation_by_admin,
                 'activation_by_user': activation_by_user,
             }
         )
     else:
-        mail_user(request, user, mail_subject, 'misago/emails/register/complete')
+        mail_user(user, mail_subject, 'misago/emails/register/complete')
 
 
 def get_registration_result_json(user):

+ 1 - 1
misago/users/views/admin/users.py

@@ -114,7 +114,7 @@ class UsersList(UserAdmin, generic.ListView):
             subject = _("Your account on %(forum_name)s forums has been activated")
             mail_subject = subject % {'forum_name': settings.forum_name}
 
-            mail_users(request, inactive_users, mail_subject, 'misago/emails/activation/by_admin')
+            mail_users(inactive_users, mail_subject, 'misago/emails/activation/by_admin')
 
             messages.success(request, _("Selected users accounts have been activated."))
 

+ 2 - 0
runtests.py

@@ -83,6 +83,8 @@ PASSWORD_HASHERS = (
     'django.contrib.auth.hashers.MD5PasswordHasher',
 )
 
+# Default misago address to test address
+MISAGO_ADDRESS = 'http://testserver/'
 
 # Use english search config
 MISAGO_SEARCH_CONFIG = 'english'