def test_non_persistent_message(self, send_email, render_to_string):
        render_to_string.return_value = 'Test'

        class TestNotification(SiteNotification):
            name = 'foo'
            success_message = 'Test success message'
            success_level = INFO_NON_PERSISTENT

        user = fixture.get(User)
        n = TestNotification(user, True)
        backend = SiteBackend(request=None)

        self.assertEqual(PersistentMessage.objects.count(), 0)
        backend.send(n)
        # No email is sent for non persistent messages
        send_email.assert_not_called()
        self.assertEqual(PersistentMessage.objects.count(), 1)
        self.assertEqual(PersistentMessage.objects.filter(read=False).count(), 1)

        self.client.force_login(user)
        response = self.client.get('/dashboard/')
        self.assertContains(response, 'Test success message')
        self.assertEqual(PersistentMessage.objects.count(), 1)
        self.assertEqual(PersistentMessage.objects.filter(read=True).count(), 1)

        response = self.client.get('/dashboard/')
        self.assertNotContains(response, 'Test success message')
Esempio n. 2
0
    def test_non_persistent_message(self, send_email, render_to_string):
        render_to_string.return_value = 'Test'

        class TestNotification(SiteNotification):
            name = 'foo'
            success_message = 'Test success message'
            success_level = INFO_NON_PERSISTENT

        user = fixture.get(User)
        # Setting the primary and verified email address of the user
        email = fixture.get(EmailAddress,
                            user=user,
                            primary=True,
                            verified=True)

        n = TestNotification(user, True)
        backend = SiteBackend(request=None)

        self.assertEqual(PersistentMessage.objects.count(), 0)
        backend.send(n)
        # No email is sent for non persistent messages
        send_email.assert_not_called()
        self.assertEqual(PersistentMessage.objects.count(), 1)
        self.assertEqual(
            PersistentMessage.objects.filter(read=False).count(), 1)

        self.client.force_login(user)
        response = self.client.get('/dashboard/')
        self.assertContains(response, 'Test success message')
        self.assertEqual(PersistentMessage.objects.count(), 1)
        self.assertEqual(
            PersistentMessage.objects.filter(read=True).count(), 1)

        response = self.client.get('/dashboard/')
        self.assertNotContains(response, 'Test success message')
Esempio n. 3
0
    def test_email_backend(self, add_message, render_to_string):
        class TestNotification(Notification):
            name = 'foo'
            subject = 'This is {{ foo.id }}'
            context_object_name = 'foo'

        build = fixture.get(Build)
        req = mock.MagicMock()
        notify = TestNotification(object=build, request=req)
        backend = SiteBackend(request=req)
        backend.send(notify)

        add_message.assert_has_calls([
            mock.call(level=21, request=req, message=mock.ANY, extra_tags='')
        ])
Esempio n. 4
0
    def test_email_backend(self, add_message, render_to_string):
        class TestNotification(Notification):
            name = 'foo'
            subject = 'This is {{ foo.id }}'
            context_object_name = 'foo'

        build = fixture.get(Build)
        user = fixture.get(User)
        req = mock.MagicMock()
        notify = TestNotification(object=build, request=req, user=user)
        backend = SiteBackend(request=req)
        backend.send(notify)

        add_message.assert_has_calls([
            mock.call(level=21, request=req, message=mock.ANY, extra_tags='',
                      user=user)
        ])
Esempio n. 5
0
    def test_message_backend(self, render_to_string):
        render_to_string.return_value = 'Test'

        class TestNotification(Notification):
            name = 'foo'
            subject = 'This is {{ foo.id }}'
            context_object_name = 'foo'

        build = fixture.get(Build)
        user = fixture.get(User)
        req = mock.MagicMock()
        notify = TestNotification(context_object=build, request=req, user=user)
        backend = SiteBackend(request=req)
        backend.send(notify)

        self.assertEqual(render_to_string.call_count, 1)
        self.assertEqual(PersistentMessage.objects.count(), 1)

        message = PersistentMessage.objects.first()
        self.assertEqual(message.user, user)
    def test_message_backend(self, render_to_string):
        render_to_string.return_value = 'Test'

        class TestNotification(Notification):
            name = 'foo'
            subject = 'This is {{ foo.id }}'
            context_object_name = 'foo'

        build = fixture.get(Build)
        user = fixture.get(User)
        req = mock.MagicMock()
        notify = TestNotification(context_object=build, request=req, user=user)
        backend = SiteBackend(request=req)
        backend.send(notify)

        self.assertEqual(render_to_string.call_count, 1)
        self.assertEqual(PersistentMessage.objects.count(), 1)

        message = PersistentMessage.objects.first()
        self.assertEqual(message.user, user)
Esempio n. 7
0
    def test_message_anonymous_user(self, render_to_string):
        """Anonymous user still throwns exception on persistent messages."""
        render_to_string.return_value = 'Test'

        class TestNotification(Notification):
            name = 'foo'
            subject = 'This is {{ foo.id }}'
            context_object_name = 'foo'

        build = fixture.get(Build)
        user = AnonymousUser()
        req = mock.MagicMock()
        notify = TestNotification(context_object=build, request=req, user=user)
        backend = SiteBackend(request=req)

        self.assertEqual(PersistentMessage.objects.count(), 0)

        # We should never be adding persistent messages for anonymous users.
        # Make sure message_extends sitll throws an exception here
        with self.assertRaises(NotImplementedError):
            backend.send(notify)

        self.assertEqual(render_to_string.call_count, 1)
        self.assertEqual(PersistentMessage.objects.count(), 0)
    def test_message_anonymous_user(self, render_to_string):
        """Anonymous user still throwns exception on persistent messages"""
        render_to_string.return_value = 'Test'

        class TestNotification(Notification):
            name = 'foo'
            subject = 'This is {{ foo.id }}'
            context_object_name = 'foo'

        build = fixture.get(Build)
        user = AnonymousUser()
        req = mock.MagicMock()
        notify = TestNotification(context_object=build, request=req, user=user)
        backend = SiteBackend(request=req)

        self.assertEqual(PersistentMessage.objects.count(), 0)

        # We should never be adding persistent messages for anonymous users.
        # Make sure message_extends sitll throws an exception here
        with self.assertRaises(NotImplementedError):
            backend.send(notify)

        self.assertEqual(render_to_string.call_count, 1)
        self.assertEqual(PersistentMessage.objects.count(), 0)
Esempio n. 9
0
def contact_users(
    users,
    email_subject=None,
    email_content=None,
    from_email=None,
    notification_content=None,
    sticky_notification=False,
    context_function=None,
    dryrun=True,
):
    """
    Send an email or a sticky notification to a list of users.

    :param users: Queryset of Users.
    :param string email_subject: Email subject
    :param string email_content: Email content (markdown)
    :param string from_email: Email to sent from (Test Support <*****@*****.**>)
    :param string notification_content: Content for the sticky notification (markdown)
    :param context_function: A callable that will receive an user
     and return a dict of additional context to be used in the email/notification content
    :param bool dryrun: If `True` don't sent the email or notification, just print the content

    The `email_content` and `notification_content` contents will be rendered using
    a template with the following context::

        {
            'user': <user object>,
            'domain': https://readthedocs.org,
        }

    :returns: A dictionary with a list of sent/failed emails/notifications.
    """
    from_email = from_email or settings.DEFAULT_FROM_EMAIL
    context_function = context_function or (lambda user: {})
    sent_emails = set()
    failed_emails = set()
    sent_notifications = set()
    failed_notifications = set()

    backend = SiteBackend(request=None)

    engine = Engine.get_default()
    notification_template = engine.from_string(notification_content or '')

    email_template = engine.from_string(email_content or '')
    email_txt_template = engine.get_template('core/email/common.txt')
    email_html_template = engine.get_template('core/email/common.html')

    class TempNotification(SiteNotification):

        if sticky_notification:
            success_level = message_constants.SUCCESS_PERSISTENT

        def render(self, *args, **kwargs):
            context = {
                'user': self.user,
                'domain': f'https://{settings.PRODUCTION_DOMAIN}',
            }
            context.update(context_function(self.user))
            return markdown.markdown(
                notification_template.render(Context(context)))

    total = users.count()
    for count, user in enumerate(users.iterator(), start=1):
        context = {
            'user': user,
            'domain': f'https://{settings.PRODUCTION_DOMAIN}',
        }
        context.update(context_function(user))

        if notification_content:
            notification = TempNotification(
                user=user,
                success=True,
            )
            try:
                if not dryrun:
                    backend.send(notification)
                else:
                    pprint(
                        markdown.markdown(
                            notification_template.render(Context(context))))
            except Exception:
                log.exception('Notification failed to send')
                failed_notifications.add(user.username)
            else:
                log.info(
                    'Successfully set notification.',
                    user_username=user.username,
                    count=count,
                    total=total,
                )
                sent_notifications.add(user.username)

        if email_subject:
            emails = list(
                user.emailaddress_set.filter(verified=True).exclude(
                    email=user.email).values_list('email', flat=True))
            emails.append(user.email)

            # First render the markdown context.
            email_txt_content = email_template.render(Context(context))
            email_html_content = markdown.markdown(email_txt_content)

            # Now render it using the base email templates.
            email_txt_rendered = email_txt_template.render(
                Context({'content': email_txt_content}))
            email_html_rendered = email_html_template.render(
                Context({'content': email_html_content}))

            try:
                kwargs = dict(
                    subject=email_subject,
                    message=email_txt_rendered,
                    html_message=email_html_rendered,
                    from_email=from_email,
                    recipient_list=emails,
                )
                if not dryrun:
                    send_mail(**kwargs)
                else:
                    pprint(kwargs)
            except Exception:
                log.exception('Email failed to send')
                failed_emails.update(emails)
            else:
                log.info('Email sent.',
                         emails=emails,
                         count=count,
                         total=total)
                sent_emails.update(emails)

    return {
        'email': {
            'sent': sent_emails,
            'failed': failed_emails,
        },
        'notification': {
            'sent': sent_notifications,
            'failed': failed_emails,
        },
    }
Esempio n. 10
0
def contact_users(
    users,
    email_subject=None,
    email_content=None,
    email_content_html=None,
    from_email=None,
    notification_content=None,
    dryrun=True,
):
    """
    Send an email or a sticky notification to a list of users.

    :param users: Queryset of Users.
    :param string email_subject: Email subject
    :param string email_content: Email content (txt)
    :param string email_content_html: Email content (HTML)
    :param string from_email: Email to sent from (Test Support <*****@*****.**>)
    :param string notification_content: Content for the sticky notification.
    :param bool dryrun: If `True` don't sent the email or notification, just print the content.

    :returns: A dictionary with a list of sent/failed emails/notifications.
    """
    from_email = from_email or settings.DEFAULT_FROM_EMAIL
    sent_emails = set()
    failed_emails = set()
    sent_notifications = set()
    failed_notifications = set()

    backend = SiteBackend(request=None)

    class TempNotification(SiteNotification):

        def render(self, *args, **kwargs):
            return notification_content

    for user in users.iterator():
        if notification_content:
            notification = TempNotification(
                user=user,
                success=True,
            )
            try:
                if not dryrun:
                    backend.send(notification)
                else:
                    pprint(notification_content)
            except Exception:
                log.exception('Notification failed to send')
                failed_notifications.add(user.pk)
            else:
                log.info('Successfully set notification user=%s', user)
                sent_notifications.add(user.pk)

        if email_subject:
            emails = list(
                user.emailaddress_set
                .filter(verified=True)
                .exclude(email=user.email)
                .values_list('email', flat=True)
            )
            emails.append(user.email)

            try:
                kwargs = dict(
                    subject=email_subject,
                    message=email_content,
                    html_message=email_content_html,
                    from_email=from_email,
                    recipient_list=emails,
                )
                if not dryrun:
                    send_mail(**kwargs)
                else:
                    pprint(kwargs)
            except Exception:
                log.exception('Mail failed to send')
                failed_emails.update(emails)
            else:
                log.info('Email sent to %s', emails)
                sent_emails.update(emails)

    return {
        'email': {
            'sent': sent_emails,
            'failed': failed_emails,
        },
        'notification': {
            'sent': sent_notifications,
            'failed': failed_emails,
        },
    }