\r
urlpatterns = patterns('postman.views',\r
# ...\r
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$',\r
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',\r
WriteView.as_view(max=3),\r
name='postman_write'),\r
# ...\r
\r
urlpatterns = patterns('postman.views',\r
# ...\r
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$',\r
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',\r
WriteView.as_view(user_filter=my_user_filter),\r
name='postman_write'),\r
# ...\r
\r
urlpatterns = patterns('postman.views',\r
# ...\r
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$',\r
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',\r
WriteView.as_view(exchange_filter=my_exchange_filter),\r
name='postman_write'),\r
# ...\r
\r
urlpatterns = patterns('postman.views',\r
# ...\r
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$',\r
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',\r
WriteView.as_view(autocomplete_channels=(None,'anonymous_ac')),\r
name='postman_write'),\r
url(r'^reply/(?P<message_id>[\d]+)/$',\r
\r
urlpatterns = patterns('postman.views',\r
# ...\r
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$',\r
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',\r
WriteView.as_view(autocomplete_channels='write_ac'), \r
name='postman_write'),\r
# ...\r
\r
urlpatterns = patterns('postman.views',\r
# ...\r
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$',\r
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',\r
WriteView.as_view(auto_moderators=(mod1, mod2)),\r
name='postman_write'),\r
url(r'^reply/(?P<message_id>[\d]+)/$',\r
\r
urlpatterns = patterns('postman.views',\r
# ...\r
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$',\r
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',\r
WriteView.as_view(form_classes=(MyCustomWriteForm, MyCustomAnonymousWriteForm)),\r
name='postman_write'),\r
url(r'^reply/(?P<message_id>[\d]+)/$',\r
def clean(self):
"""Check some validity constraints."""
- if not (self.sender_id or self.email):
+ if not (self.sender_id is not None or self.email):
raise ValidationError(ugettext("Undefined sender."))
def clean_moderation(self, initial_status, user=None):
def clean_for_visitor(self):
"""Do some auto-read and auto-delete, because there is no one to do it (no account)."""
- if not self.sender_id:
+ if self.sender_id is None:
# no need to wait for a final moderation status to mark as deleted
if not self.sender_deleted_at:
self.sender_deleted_at = now()
- elif not self.recipient_id:
+ elif self.recipient_id is None:
if self.is_accepted():
if not self.read_at:
self.read_at = now()
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', site)
+ if not (self.sender_id is not None and is_auto_moderated):
+ (notify_user if self.sender_id is not None else email_visitor)(self, 'rejection', site)
elif self.is_accepted():
- (notify_user if self.recipient_id else email_visitor)(self, 'acceptance', site)
+ (notify_user if self.recipient_id is not None else email_visitor)(self, 'acceptance', site)
def get_dates(self):
"""Get some dates to restore later."""
-"""
+"""
Test suite.
- Do not put 'mailer' in INSTALLED_APPS, it disturbs the emails counting.
response = self.client.get(url)
self.assertContains(response, 'value="bar, foo"')
+ # because of Custom User Model, do allow almost any character, not only '^[\w.@+-]+$' of the legacy django.contrib.auth.User model
+ get_user_model().objects.create_user("Le Créac'h", 'foobar@domain.com', 'pass') # even: space, accentued, qootes
+ url = reverse('postman_write', args=["Le Créac'h"])
+ response = self.client.get(url)
+ self.assertContains(response, 'value="Le Créac'h"')
+
def test_write_auto_complete(self):
"Test the 'autocomplete_channels' parameter."
url = reverse('postman_write_auto_complete')
x X---
"""
- m1 = self.c12(moderation_status=STATUS_PENDING);
+ m1 = self.c12(moderation_status=STATUS_PENDING)
m2 = self.c12(moderation_status=STATUS_REJECTED, recipient_deleted_at=now())
m3 = self.c12()
m3.read_at, m3.thread = now(), m3
def test_notification_rejection_user(self):
"Test notify_users() for rejection, sender is a User."
- m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender = self.user1, recipient=self.user2)
+ m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender=self.user1, recipient=self.user2)
self.check_notification(m, 1, self.user1.email, is_auto_moderated=False, notice_label='postman_rejection')
def test_notification_rejection_user_auto_moderated(self):
"Test notify_users() for rejection, sender is a User, and is alerted online."
- m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender = self.user1, recipient=self.user2)
+ m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender=self.user1, recipient=self.user2)
self.check_notification(m, 0, is_auto_moderated=True)
def test_notification_rejection_user_inactive(self):
"Test notify_users() for rejection, sender is a User, but must be active."
- m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender = self.user1, recipient=self.user2)
+ m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender=self.user1, recipient=self.user2)
self.user1.is_active = False
self.check_notification(m, 0, is_auto_moderated=False, notice_label='postman_rejection')
def test_notification_rejection_user_disable(self):
"Test notify_users() for rejection, sender is a User, but emailing is disabled."
- m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender = self.user1, recipient=self.user2)
+ m = Message.objects.create(subject='s', moderation_status=STATUS_REJECTED, sender=self.user1, recipient=self.user2)
settings.POSTMAN_DISABLE_USER_EMAILING = True
settings.POSTMAN_NOTIFIER_APP = None
self.reload_modules()
def test_notification_acceptance_user(self):
"Test notify_users() for acceptance, recipient is a User."
- m = Message.objects.create(subject='s', moderation_status=STATUS_ACCEPTED, sender=self.user1, recipient = self.user2)
+ m = Message.objects.create(subject='s', moderation_status=STATUS_ACCEPTED, sender=self.user1, recipient=self.user2)
self.check_notification(m, 1, self.user2.email, notice_label='postman_message')
def test_notification_acceptance_user_inactive(self):
"Test notify_users() for acceptance, recipient is a User, but must be active."
- m = Message.objects.create(subject='s', moderation_status=STATUS_ACCEPTED, sender=self.user1, recipient = self.user2)
+ m = Message.objects.create(subject='s', moderation_status=STATUS_ACCEPTED, sender=self.user1, recipient=self.user2)
self.user2.is_active = False
self.check_notification(m, 0, notice_label='postman_message')
def test_notification_acceptance_user_disable(self):
"Test notify_users() for acceptance, recipient is a User, but emailing is disabled."
- m = Message.objects.create(subject='s', moderation_status=STATUS_ACCEPTED, sender=self.user1, recipient = self.user2)
+ m = Message.objects.create(subject='s', moderation_status=STATUS_ACCEPTED, sender=self.user1, recipient=self.user2)
settings.POSTMAN_DISABLE_USER_EMAILING = True
settings.POSTMAN_NOTIFIER_APP = None
self.reload_modules()
url(r'^sent/(?:(?P<option>'+OPTIONS+')/)?$', SentView.as_view(), name='postman_sent'),
url(r'^archives/(?:(?P<option>'+OPTIONS+')/)?$', ArchivesView.as_view(), name='postman_archives'),
url(r'^trash/(?:(?P<option>'+OPTIONS+')/)?$', TrashView.as_view(), name='postman_trash'),
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(), name='postman_write'),
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(), name='postman_write'),
url(r'^reply/(?P<message_id>[\d]+)/$', ReplyView.as_view(), name='postman_reply'),
url(r'^view/(?P<message_id>[\d]+)/$', MessageView.as_view(), name='postman_view'),
url(r'^view/t/(?P<thread_id>[\d]+)/$', ConversationView.as_view(), name='postman_view_conversation'),
url(r'^sent/(?:(?P<option>'+OPTIONS+')/)?$', SentView.as_view(), name='postman_sent'),
url(r'^archives/(?:(?P<option>'+OPTIONS+')/)?$', ArchivesView.as_view(), name='postman_archives'),
url(r'^trash/(?:(?P<option>'+OPTIONS+')/)?$', TrashView.as_view(), name='postman_trash'),
- url(r'^write/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(), name='postman_write'),
+ url(r'^write/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(), name='postman_write'),
url(r'^reply/(?P<message_id>[\d]+)/$', ReplyView.as_view(), name='postman_reply'),
url(r'^view/(?P<message_id>[\d]+)/$', MessageView.as_view(), name='postman_view'),
url(r'^view/t/(?P<thread_id>[\d]+)/$', ConversationView.as_view(), name='postman_view_conversation'),
# Customized set
# 'success_url'
- url(r'^write_sent/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(success_url='postman_sent'), name='postman_write_with_success_url_to_sent'),
+ url(r'^write_sent/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(success_url='postman_sent'), name='postman_write_with_success_url_to_sent'),
url(r'^reply_sent/(?P<message_id>[\d]+)/$', ReplyView.as_view(success_url='postman_sent'), name='postman_reply_with_success_url_to_sent'),
url(r'^archive_arch/$', ArchiveView.as_view(success_url='postman_archives'), name='postman_archive_with_success_url_to_archives'),
url(r'^delete_arch/$', DeleteView.as_view(success_url='postman_archives'), name='postman_delete_with_success_url_to_archives'),
url(r'^undelete_arch/$', UndeleteView.as_view(success_url='postman_archives'), name='postman_undelete_with_success_url_to_archives'),
# 'max'
- url(r'^write_max/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(max=1), name='postman_write_with_max'),
+ url(r'^write_max/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(max=1), name='postman_write_with_max'),
url(r'^reply_max/(?P<message_id>[\d]+)/$', ReplyView.as_view(max=1), name='postman_reply_with_max'),
# 'user_filter' on write
- url(r'^write_user_filter_reason/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(user_filter=user_filter_reason), name='postman_write_with_user_filter_reason'),
- url(r'^write_user_filter_no_reason/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(user_filter=user_filter_no_reason), name='postman_write_with_user_filter_no_reason'),
- url(r'^write_user_filter_false/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(user_filter=user_filter_false), name='postman_write_with_user_filter_false'),
- url(r'^write_user_filter_exception/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(user_filter=user_filter_exception), name='postman_write_with_user_filter_exception'),
+ url(r'^write_user_filter_reason/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(user_filter=user_filter_reason), name='postman_write_with_user_filter_reason'),
+ url(r'^write_user_filter_no_reason/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(user_filter=user_filter_no_reason), name='postman_write_with_user_filter_no_reason'),
+ url(r'^write_user_filter_false/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(user_filter=user_filter_false), name='postman_write_with_user_filter_false'),
+ url(r'^write_user_filter_exception/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(user_filter=user_filter_exception), name='postman_write_with_user_filter_exception'),
# 'user_filter' on reply
url(r'^reply_user_filter_reason/(?P<message_id>[\d]+)/$', ReplyView.as_view(user_filter=user_filter_reason), name='postman_reply_with_user_filter_reason'),
url(r'^reply_user_filter_no_reason/(?P<message_id>[\d]+)/$', ReplyView.as_view(user_filter=user_filter_no_reason), name='postman_reply_with_user_filter_no_reason'),
url(r'^reply_user_filter_false/(?P<message_id>[\d]+)/$', ReplyView.as_view(user_filter=user_filter_false), name='postman_reply_with_user_filter_false'),
url(r'^reply_user_filter_exception/(?P<message_id>[\d]+)/$', ReplyView.as_view(user_filter=user_filter_exception), name='postman_reply_with_user_filter_exception'),
# 'exchange_filter' on write
- url(r'^write_exch_filter_reason/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_reason), name='postman_write_with_exch_filter_reason'),
- url(r'^write_exch_filter_no_reason/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_no_reason), name='postman_write_with_exch_filter_no_reason'),
- url(r'^write_exch_filter_false/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_false), name='postman_write_with_exch_filter_false'),
- url(r'^write_exch_filter_exception/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_exception), name='postman_write_with_exch_filter_exception'),
+ url(r'^write_exch_filter_reason/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_reason), name='postman_write_with_exch_filter_reason'),
+ url(r'^write_exch_filter_no_reason/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_no_reason), name='postman_write_with_exch_filter_no_reason'),
+ url(r'^write_exch_filter_false/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_false), name='postman_write_with_exch_filter_false'),
+ url(r'^write_exch_filter_exception/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(exchange_filter=exch_filter_exception), name='postman_write_with_exch_filter_exception'),
# 'exchange_filter' on reply
url(r'^reply_exch_filter_reason/(?P<message_id>[\d]+)/$', ReplyView.as_view(exchange_filter=exch_filter_reason), name='postman_reply_with_exch_filter_reason'),
url(r'^reply_exch_filter_no_reason/(?P<message_id>[\d]+)/$', ReplyView.as_view(exchange_filter=exch_filter_no_reason), name='postman_reply_with_exch_filter_no_reason'),
url(r'^reply_exch_filter_false/(?P<message_id>[\d]+)/$', ReplyView.as_view(exchange_filter=exch_filter_false), name='postman_reply_with_exch_filter_false'),
url(r'^reply_exch_filter_exception/(?P<message_id>[\d]+)/$', ReplyView.as_view(exchange_filter=exch_filter_exception), name='postman_reply_with_exch_filter_exception'),
# 'auto_moderators'
- url(r'^write_moderate/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(auto_moderators=(moderate_as_51,moderate_as_48)), name='postman_write_moderate'),
+ url(r'^write_moderate/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(auto_moderators=(moderate_as_51,moderate_as_48)), name='postman_write_moderate'),
url(r'^reply_moderate/(?P<message_id>[\d]+)/$', ReplyView.as_view(auto_moderators=(moderate_as_51,moderate_as_48)), name='postman_reply_moderate'),
# 'formatters'
url(r'^reply_formatters/(?P<message_id>[\d]+)/$', ReplyView.as_view(formatters=(format_subject, format_body)), name='postman_reply_formatters'),
url(r'^view_formatters/(?P<message_id>[\d]+)/$', MessageView.as_view(formatters=(format_subject, format_body)), name='postman_view_formatters'),
# auto-complete
- url(r'^write_ac/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(autocomplete_channels=('postman_multiple_as1-1', None)), name='postman_write_auto_complete'),
+ url(r'^write_ac/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(autocomplete_channels=('postman_multiple_as1-1', None)), name='postman_write_auto_complete'),
url(r'^reply_ac/(?P<message_id>[\d]+)/$', ReplyView.as_view(autocomplete_channel='postman_multiple_as1-1'), name='postman_reply_auto_complete'),
# 'template_name'
url(r'^inbox_template/(?:(?P<option>'+OPTIONS+')/)?$', InboxView.as_view(template_name='postman/fake.html'), name='postman_inbox_template'),
url(r'^sent_template/(?:(?P<option>'+OPTIONS+')/)?$', SentView.as_view(template_name='postman/fake.html'), name='postman_sent_template'),
url(r'^archives_template/(?:(?P<option>'+OPTIONS+')/)?$', ArchivesView.as_view(template_name='postman/fake.html'), name='postman_archives_template'),
url(r'^trash_template/(?:(?P<option>'+OPTIONS+')/)?$', TrashView.as_view(template_name='postman/fake.html'), name='postman_trash_template'),
- url(r'^write_template/(?:(?P<recipients>[\w.@+-:]+)/)?$', WriteView.as_view(template_name='postman/fake.html'), name='postman_write_template'),
+ url(r'^write_template/(?:(?P<recipients>[^/#]+)/)?$', WriteView.as_view(template_name='postman/fake.html'), name='postman_write_template'),
url(r'^reply_template/(?P<message_id>[\d]+)/$', ReplyView.as_view(template_name='postman/fake.html'), name='postman_reply_template'),
url(r'^view_template/(?P<message_id>[\d]+)/$', MessageView.as_view(template_name='postman/fake.html'), name='postman_view_template'),
url(r'^view_template/t/(?P<thread_id>[\d]+)/$', ConversationView.as_view(template_name='postman/fake.html'), name='postman_view_conversation_template'),