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)
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 /> """, )
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'*****@*****.**']
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)