From 5fef6d2445509c2f071d06b348ca001be9e7ab05 Mon Sep 17 00:00:00 2001 From: Ronny Vedrilla Date: Thu, 20 Jun 2024 11:03:32 +0200 Subject: [PATCH] Fixed #35528 -- Added EmailMultiAlternatives.body_contains() helper method. --- django/core/mail/message.py | 13 +++++++++++++ docs/releases/5.2.txt | 4 ++++ docs/topics/email.txt | 20 ++++++++++++++++++++ tests/mail/tests.py | 18 ++++++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/django/core/mail/message.py b/django/core/mail/message.py index 7eee5da8b8..2eb8aa354b 100644 --- a/django/core/mail/message.py +++ b/django/core/mail/message.py @@ -505,3 +505,16 @@ class EmailMultiAlternatives(EmailMessage): ) ) return msg + + def body_contains(self, text): + """ + Checks that ``text`` occurs in the email body and in all attached MIME + type text/* alternatives. + """ + if text not in self.body: + return False + + for content, mimetype in self.alternatives: + if mimetype.startswith("text/") and text not in content: + return False + return True diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index 61101ce1fd..8b77ecc482 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -143,6 +143,10 @@ Email ` is now a list of named tuples, as opposed to regular tuples. +* The new :meth:`~django.core.mail.EmailMultiAlternatives.body_contains` method + returns a boolean indicating whether a provided text is contained in the + email ``body`` and in all attached MIME type ``text/*`` alternatives. + Error Reporting ~~~~~~~~~~~~~~~ diff --git a/docs/topics/email.txt b/docs/topics/email.txt index 635864a95e..e5d4f277f5 100644 --- a/docs/topics/email.txt +++ b/docs/topics/email.txt @@ -436,6 +436,26 @@ Django's email library, you can do this using the msg.attach_alternative(html_content, "text/html") msg.send() + .. method:: body_contains(text) + + .. versionadded:: 5.2 + + Returns a boolean indicating whether the provided ``text`` is + contained in the email ``body`` and in all attached MIME type + ``text/*`` alternatives. + + This can be useful when testing emails. For example:: + + def test_contains_email_content(self): + subject = "Hello World" + from_email = "from@example.com" + to = "to@example.com" + msg = EmailMultiAlternatives(subject, "I am content.", from_email, [to]) + msg.attach_alternative("

I am content.

", "text/html") + + self.assertIs(msg.body_contains("I am content"), True) + self.assertIs(msg.body_contains("

I am content.

"), False) + Updating the default content type ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/mail/tests.py b/tests/mail/tests.py index 3746ede338..1f7cbbadca 100644 --- a/tests/mail/tests.py +++ b/tests/mail/tests.py @@ -1163,6 +1163,24 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): with self.assertRaisesMessage(ValueError, msg): email_msg.attach_alternative("

content

", None) + def test_body_contains(self): + email_msg = EmailMultiAlternatives() + email_msg.body = "I am content." + self.assertIs(email_msg.body_contains("I am"), True) + self.assertIs(email_msg.body_contains("I am content."), True) + + email_msg.attach_alternative("

I am different content.

", "text/html") + self.assertIs(email_msg.body_contains("I am"), True) + self.assertIs(email_msg.body_contains("I am content."), False) + self.assertIs(email_msg.body_contains("

I am different content.

"), False) + + def test_body_contains_alternative_non_text(self): + email_msg = EmailMultiAlternatives() + email_msg.body = "I am content." + email_msg.attach_alternative("I am content.", "text/html") + email_msg.attach_alternative(b"I am a song.", "audio/mpeg") + self.assertIs(email_msg.body_contains("I am content"), True) + @requires_tz_support class MailTimeZoneTests(SimpleTestCase):