From a1f7f899c94f3b02baeaeb34bae1c7315338d20c Mon Sep 17 00:00:00 2001 From: aptalca <541623+aptalca@users.noreply.github.com> Date: Thu, 23 Nov 2023 07:51:51 -0500 Subject: [PATCH] Make SMTP notify send images as attachments if html is disabled (#93562) smtp notify: send images without html as attachments update smtp test to detect content_type for plain txt + image --- homeassistant/components/smtp/notify.py | 47 ++++++++++++++----------- tests/components/smtp/test_notify.py | 2 +- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/smtp/notify.py b/homeassistant/components/smtp/notify.py index 6836a0b9f6b..6b960409305 100644 --- a/homeassistant/components/smtp/notify.py +++ b/homeassistant/components/smtp/notify.py @@ -185,9 +185,8 @@ class MailNotificationService(BaseNotificationService): def send_message(self, message="", **kwargs): """Build and send a message to a user. - Will send plain text normally, or will build a multipart HTML message - with inline image attachments if images config is defined, or will - build a multipart HTML if html config is defined. + Will send plain text normally, with pictures as attachments if images config is + defined, or will build a multipart HTML if html config is defined. """ subject = kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT) @@ -242,8 +241,12 @@ def _build_text_msg(message): return MIMEText(message) -def _attach_file(atch_name, content_id): - """Create a message attachment.""" +def _attach_file(atch_name, content_id=""): + """Create a message attachment. + + If MIMEImage is successful and content_id is passed (HTML), add images in-line. + Otherwise add them as attachments. + """ try: with open(atch_name, "rb") as attachment_file: file_bytes = attachment_file.read() @@ -258,32 +261,34 @@ def _attach_file(atch_name, content_id): "Attachment %s has an unknown MIME type. Falling back to file", atch_name, ) - attachment = MIMEApplication(file_bytes, Name=atch_name) - attachment["Content-Disposition"] = f'attachment; filename="{atch_name}"' + attachment = MIMEApplication(file_bytes, Name=os.path.basename(atch_name)) + attachment[ + "Content-Disposition" + ] = f'attachment; filename="{os.path.basename(atch_name)}"' + else: + if content_id: + attachment.add_header("Content-ID", f"<{content_id}>") + else: + attachment.add_header( + "Content-Disposition", + f"attachment; filename={os.path.basename(atch_name)}", + ) - attachment.add_header("Content-ID", f"<{content_id}>") return attachment def _build_multipart_msg(message, images): - """Build Multipart message with in-line images.""" - _LOGGER.debug("Building multipart email with embedded attachment(s)") - msg = MIMEMultipart("related") - msg_alt = MIMEMultipart("alternative") - msg.attach(msg_alt) + """Build Multipart message with images as attachments.""" + _LOGGER.debug("Building multipart email with image attachment(s)") + msg = MIMEMultipart() body_txt = MIMEText(message) - msg_alt.attach(body_txt) - body_text = [f"

{message}


"] + msg.attach(body_txt) - for atch_num, atch_name in enumerate(images): - cid = f"image{atch_num}" - body_text.append(f'
') - attachment = _attach_file(atch_name, cid) + for atch_name in images: + attachment = _attach_file(atch_name) if attachment: msg.attach(attachment) - body_html = MIMEText("".join(body_text), "html") - msg_alt.attach(body_html) return msg diff --git a/tests/components/smtp/test_notify.py b/tests/components/smtp/test_notify.py index 86a21c754ed..bca5a5674df 100644 --- a/tests/components/smtp/test_notify.py +++ b/tests/components/smtp/test_notify.py @@ -101,7 +101,7 @@ EMAIL_DATA = [ ( "Test msg", {"images": ["tests/testing_config/notify/test.jpg"]}, - "Content-Type: multipart/related", + "Content-Type: multipart/mixed", ), ( "Test msg",