\r
The available context variables are:\r
\r
-* ``site``: the Site instance\r
+* ``site``: the *Site* instance if the "sites" framework is installed, otherwise a *RequestSite* instance\r
+ with a fallback to *None* in the case of the API\r
* ``object``: the Message instance\r
* ``action``: 'rejection' or 'acceptance'\r
\r
from django import forms
from django.contrib import admin
+from django.contrib.sites.models import get_current_site
from django.db import transaction
from django.utils.translation import ugettext, ugettext_lazy as _
obj.clean_for_visitor()
super(MessageAdmin, self).save_model(request, obj, form, change)
obj.update_parent(form.initial_status)
- obj.notify_users(form.initial_status, is_auto_moderated=False)
+ obj.notify_users(form.initial_status, get_current_site(request), is_auto_moderated=False)
class PendingMessageAdminForm(forms.ModelForm):
"""
from __future__ import unicode_literals
+from django.contrib.sites.models import Site
try:
from django.utils.timezone import now # Django 1.4 aware datetimes
except ImportError:
from postman.models import Message, STATUS_PENDING, STATUS_ACCEPTED
+
+def _get_site():
+ # do not require the sites framework to be installed ; and no request object is available here
+ return Site.objects.get_current() if Site._meta.installed else None
+
+
def pm_broadcast(sender, recipients, subject, body='', skip_notification=False):
"""
Broadcast a message to multiple Users.
message.pk = None
message.save()
if not skip_notification:
- message.notify_users(STATUS_PENDING)
+ message.notify_users(STATUS_PENDING, _get_site())
+
def pm_write(sender, recipient, subject, body='', skip_notification=False,
auto_archive=False, auto_delete=False, auto_moderators=None):
message.sender_deleted_at = now()
message.save()
if not skip_notification:
- message.notify_users(initial_status)
+ message.notify_users(initial_status, _get_site())
user_filter = kwargs.pop('user_filter', None)
max = kwargs.pop('max', None)
channel = kwargs.pop('channel', None)
+ self.site = kwargs.pop('site', None)
super(BaseWriteForm, self).__init__(*args, **kwargs)
self.instance.sender = sender if (sender and sender.is_authenticated()) else None
if self.instance.is_rejected():
is_successful = False
self.instance.update_parent(initial_status)
- self.instance.notify_users(initial_status)
+ self.instance.notify_users(initial_status, self.site)
# some resets for next reuse
if not isinstance(r, get_user_model()):
self.instance.email = ''
parent.replied_at = None
parent.save()
- def notify_users(self, initial_status, is_auto_moderated=True):
+ def notify_users(self, initial_status, site, is_auto_moderated=True):
"""Notify the rejection (to sender) or the acceptance (to recipient) of the message."""
if initial_status == STATUS_PENDING:
if self.is_rejected():
# Bypass: for an online user, no need to notify when rejection is immediate.
# Only useful for a visitor as an archive copy of the message, otherwise lost.
if not (self.sender_id and is_auto_moderated):
- (notify_user if self.sender_id else email_visitor)(self, 'rejection')
+ (notify_user if self.sender_id else email_visitor)(self, 'rejection', site)
elif self.is_accepted():
- (notify_user if self.recipient_id else email_visitor)(self, 'acceptance')
+ (notify_user if self.recipient_id else email_visitor)(self, 'acceptance', site)
def get_dates(self):
"""Get some dates to restore later."""
base.html
404.html
-To have a fast test session, you can set a minimal configuration as:
+To have a fast test session, set a minimal configuration as:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
- 'django.contrib.sites',
+ # 'django.contrib.sites', # is optional
'django.contrib.admin',
- # 'pagination', # or use the mock
- # 'ajax_select', # is an option
- # 'notification', # is an option
+ # 'pagination', # or use the mock
+ # 'ajax_select', # is an option
+ # 'notification', # is an option
'postman',
)
except ImportError:
from postman.future_1_5 import get_user_model
from django.contrib.auth.models import AnonymousUser
+from django.contrib.sites.models import Site
from django.core import mail
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse, clear_url_caches, get_resolver, get_urlconf
self.check_status(Message.objects.get(), status=STATUS_REJECTED, recipient_deleted_at=True,
moderation_date=True, moderation_reason="some reason")
+ def test_write_notification(self):
+ "Test the fallback for the site name in the generation of a notification, when the django.contrib.sites app is not installed."
+ settings.POSTMAN_AUTO_MODERATE_AS = True # will generate an acceptance notification
+ url = reverse('postman_write')
+ data = {'subject': 's', 'body': 'b', 'recipients': self.user2.get_username()}
+ self.assertTrue(self.client.login(username='foo', password='pass'))
+ response = self.client.post(url, data, HTTP_REFERER=url)
+ self.assertRedirects(response, url)
+ self.check_status(Message.objects.get(), status=STATUS_ACCEPTED, moderation_date=True)
+ self.assertEqual(len(mail.outbox), 1)
+ # can't use get_current_site(response.request) because response.request is not an HttpRequest and doesn't have a get_host attribute
+ if Site._meta.installed:
+ sitename = Site.objects.get_current().name
+ else:
+ sitename = "testserver" # the SERVER_NAME environment variable is not accessible here
+ self.assertTrue(sitename in mail.outbox[0].subject)
+
def test_reply_authentication(self):
"Test permission and what template & form are used."
template = "postman/reply.html"
def check_notification(self, m, mail_number, email=None, is_auto_moderated=True, notice_label=None):
"Check number of mails, recipient, and notice creation."
- m.notify_users(STATUS_PENDING, is_auto_moderated)
+ m.notify_users(STATUS_PENDING, Site.objects.get_current() if Site._meta.installed else None, is_auto_moderated)
self.assertEqual(len(mail.outbox), mail_number)
if mail_number:
self.assertEqual(mail.outbox[0].to, [email])
from textwrap import TextWrapper
from django.conf import settings
-from django.contrib.sites.models import Site
from django.template.loader import render_to_string
from django.utils.encoding import force_unicode
from django.utils.translation import ugettext, ugettext_lazy as _
return subject if re.match(pattern, subject, re.IGNORECASE) else str.format(subject=subject)
-def email(subject_template, message_template, recipient_list, object, action=None):
+def email(subject_template, message_template, recipient_list, object, action, site):
"""Compose and send an email."""
- site = Site.objects.get_current()
ctx_dict = {'site': site, 'object': object, 'action': action}
subject = render_to_string(subject_template, ctx_dict)
# Email subject *must not* contain newlines
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, recipient_list, fail_silently=True)
-def email_visitor(object, action):
+def email_visitor(object, action, site):
"""Email a visitor."""
- email('postman/email_visitor_subject.txt', 'postman/email_visitor.txt', [object.email], object, action)
+ email('postman/email_visitor_subject.txt', 'postman/email_visitor.txt', [object.email], object, action, site)
-def notify_user(object, action):
+def notify_user(object, action, site):
"""Notify a user."""
if action == 'rejection':
user = object.sender
notification.send(users=[user], label=label, extra_context={'pm_message': object, 'pm_action': action})
else:
if not DISABLE_USER_EMAILING and user.email and user.is_active:
- email('postman/email_user_subject.txt', 'postman/email_user.txt', [user.email], object, action)
+ email('postman/email_user_subject.txt', 'postman/email_user.txt', [user.email], object, action, site)
from django.contrib.auth import get_user_model # Django 1.5
except ImportError:
from postman.future_1_5 import get_user_model
+from django.contrib.sites.models import get_current_site
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import Http404
'user_filter': self.user_filter,
'exchange_filter': self.exchange_filter,
'max': self.max,
+ 'site': get_current_site(self.request),
})
return kwargs