示例#1
0
    def _get_rendered_message(self):
        channel = DjangoEmailChannel()
        message = Message(
            app_label='testapp',
            name='testmessage',
            options={},
            recipient=Recipient(lms_user_id=123, email_address='*****@*****.**'),
        )

        return render(channel, message)
示例#2
0
    def setUp(self):
        super().setUp()

        self.channel = DjangoEmailChannel()
        self.message = Message(
            app_label='testapp',
            name='testmessage',
            options={
                'from_address': '*****@*****.**',
            },
            recipient=Recipient(lms_user_id=123, email_address='*****@*****.**'),
        )

        self.mock_rendered_message = Mock(
            subject='\n Hello from  \r\nRobot ! \n',
            body='Just trying to see what is like to talk to a human!',
            body_html="""
                <p>Just trying to see what is like to talk to a human!</p>

                <hr />
            """,
        )
示例#3
0
class TestDjangoEmailChannel(TestCase):
    def setUp(self):
        super(TestDjangoEmailChannel, self).setUp()

        self.channel = DjangoEmailChannel()
        self.message = Message(
            app_label=u'testapp',
            name=u'testmessage',
            options={
                u'from_address': u'*****@*****.**',
            },
            recipient=Recipient(username=u'Robot',
                                email_address=u'*****@*****.**'),
        )

        self.mock_rendered_message = Mock(
            subject=u'\n Hello from  \r\nRobot ! \n',
            body=u'Just trying to see what is like to talk to a human!',
            body_html=u"""
                <p>Just trying to see what is like to talk to a human!</p>

                <hr />
            """,
        )

    def _get_rendered_message(self):
        channel = DjangoEmailChannel()
        message = Message(
            app_label=u'testapp',
            name=u'testmessage',
            options={},
            recipient=Recipient(username=u'Robot',
                                email_address=u'*****@*****.**'),
        )

        return render(channel, message)

    def test_enabled_method(self):
        assert self.channel.enabled()

    def test_happy_path(self):
        self.channel.deliver(self.message, self.mock_rendered_message)

        sent_email = mail.outbox[0]

        html_body, _ = sent_email.alternatives[0]

        assert sent_email.subject == u'Hello from Robot !'
        assert u'Just trying to see what' in sent_email.body
        assert sent_email.to == [u'*****@*****.**']

        assert u'talk to a human!</p>' in html_body

    @patch(u'django.core.mail.EmailMultiAlternatives.send',
           side_effect=SMTPException)
    def test_smtp_failure(self, _send):
        with self.assertRaises(FatalChannelDeliveryError):
            self.channel.deliver(self.message, self.mock_rendered_message)

    @override_settings(DEFAULT_FROM_EMAIL=None)
    def test_with_no_from_address_without_default(self):
        message = Message(
            app_label=u'testapp',
            name=u'testmessage',
            options={},
            recipient=Recipient(username=u'Robot',
                                email_address=u'*****@*****.**'),
        )

        with self.assertRaises(FatalChannelDeliveryError):
            self.channel.deliver(message, self.mock_rendered_message)

    @override_settings(DEFAULT_FROM_EMAIL=u'*****@*****.**')
    def test_with_no_from_address_with_default(self):
        message = Message(
            app_label=u'testapp',
            name=u'testmessage',
            options={},
            recipient=Recipient(username=u'Robot',
                                email_address=u'*****@*****.**'),
        )

        self.channel.deliver(message, self.mock_rendered_message)
        assert len(mail.outbox) == 1, u'Should have one email'

    def test_render_email_with_django_channel(self):
        rendered_email = self._get_rendered_message()
        assert u'{beacon_src}' not in rendered_email.body_html
        assert u'{view_url}' not in rendered_email.body_html
        assert u'{optout_confirm_url}' not in rendered_email.body_html

    def test_happy_sending_rendered_email(self):
        rendered_message = self._get_rendered_message()
        self.channel.deliver(self.message, rendered_message)

        assert mail.outbox, u'Should send the message'

        html_email = mail.outbox[0].alternatives[0][0]
        assert u'template head.html' in html_email
        assert u'template body.html' in html_email

    def test_happy_email_with_reply_to(self):
        rendered_message = self._get_rendered_message()
        self.message.options[u'reply_to'] = [u'*****@*****.**']
        self.channel.deliver(self.message, rendered_message)

        sent_email = mail.outbox[0]

        assert sent_email.reply_to == [u'*****@*****.**']
示例#4
0
    def deliver(self, message, rendered_message):
        if not self.enabled():
            raise FatalChannelDeliveryError(
                'Braze channel is disabled, unable to send')

        if not message.recipient.lms_user_id:
            # This channel assumes that you have Braze configured with LMS user_ids as your external_user_id in Braze.
            # Unfortunately, that means that we can't send emails to users that aren't registered with the LMS,
            # which some callers of ACE may attempt to do (despite the lms_user_id being a required Recipient field).
            # In these cases, we fall back to a simple Django smtp email.
            DjangoEmailChannel().deliver(message, rendered_message)
            return

        transactional = message.options.get('transactional', False)
        body_html = self.make_simple_html_template(rendered_message.head_html,
                                                   rendered_message.body_html)

        # Allow our settings to override the from address, because Braze requires specific configured from addresses,
        # which are tied to specific ip addresses that are "ip warmed" to help delivery of the emails not get sent
        # to promotional/spam inboxes.
        from_address = getattr(settings, self._FROM_EMAIL_SETTING,
                               None) or self.get_from_address(message)

        logger = message.get_message_specific_logger(LOG)
        logger.debug('Sending to Braze')

        # https://www.braze.com/docs/api/endpoints/messaging/send_messages/post_send_messages/
        # https://www.braze.com/docs/api/objects_filters/email_object/
        response = requests.post(
            self._send_url(),
            headers=self._auth_headers(),
            json={
                'external_user_ids': [str(message.recipient.lms_user_id)],
                'recipient_subscription_state':
                'all' if transactional else 'subscribed',
                'campaign_id': self._campaign_id(message.name),
                'messages': {
                    'email': {
                        'app_id': getattr(settings, self._APP_ID_SETTING),
                        'subject': self.get_subject(rendered_message),
                        'from': from_address,
                        'reply_to': message.options.get('reply_to'),
                        'body': body_html,
                        'plaintext_body': rendered_message.body,
                        'message_variation_id':
                        self._variation_id(message.name),
                        'should_inline_css':
                        False,  # this feature messes with inline CSS already in ACE templates
                    },
                },
            },
        )

        try:
            response.raise_for_status()
            logger.debug('Successfully sent to Braze (dispatch ID %s)',
                         response.json()['dispatch_id'])

        except requests.exceptions.HTTPError as exc:
            # https://www.braze.com/docs/api/errors/
            message = response.json().get('message', 'Unknown error')
            logger.debug('Failed to send to Braze: %s', message)
            self._handle_error_response(response, message, exc)