diff --git a/frappe/email/email_body.py b/frappe/email/email_body.py
index 5dc3054843..4ef17acef6 100755
--- a/frappe/email/email_body.py
+++ b/frappe/email/email_body.py
@@ -210,7 +210,18 @@ class EMail:
if has_inline_images:
# process inline images
- message, _inline_images = replace_filename_with_cid(message)
+ provided_images = {}
+ if inline_images:
+ for img in inline_images:
+ if img.get("filename") and img.get("filecontent"):
+ # index by full path and basename for flexible matching
+ provided_images[img["filename"]] = img["filecontent"]
+ basename = img["filename"].rsplit("/", 1)[-1]
+ if basename not in provided_images:
+ provided_images[basename] = img["filecontent"]
+
+ # process inline images while preferring provided_images over disk reads
+ message, _inline_images = replace_filename_with_cid(message, provided_images)
# prepare parts
msg_related = MIMEMultipart("related", policy=policy.SMTP)
@@ -552,11 +563,22 @@ def get_footer(email_account, footer=None):
return footer
-def replace_filename_with_cid(message):
+def replace_filename_with_cid(message, provided_images=None):
"""Replaces with
and return the modified message and
a list of inline_images with {filename, filecontent, content_id}
+
+ Args:
+ message: The HTML message to process
+ provided_images: A dictionary of images to use instead of reading from disk
+ Example:
+ {
+ "assets/frappe/images/filename.jpg": filecontent,
+ "filename.jpg": filecontent,
+ }
"""
+ if provided_images is None:
+ provided_images = {}
inline_images = []
@@ -571,7 +593,11 @@ def replace_filename_with_cid(message):
img_path_escaped = frappe.utils.html_utils.unescape_html(img_path)
filename = img_path_escaped.rsplit("/")[-1]
- filecontent = get_filecontent_from_path(img_path_escaped)
+ # check if the image is provided in the provided_images(by checking full path and basename)
+ filecontent = provided_images.get(img_path_escaped) or provided_images.get(filename)
+ if not filecontent:
+ filecontent = get_filecontent_from_path(img_path_escaped)
+
if not filecontent:
message = re.sub(f"""embed=['"]{re.escape(img_path)}['"]""", "", message)
continue
diff --git a/frappe/email/test_email_body.py b/frappe/email/test_email_body.py
index 2152c50917..bd10cc1632 100644
--- a/frappe/email/test_email_body.py
+++ b/frappe/email/test_email_body.py
@@ -137,6 +137,39 @@ w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
""".format(inline_images[0].get("content_id"))
self.assertEqual(message, processed_message)
+ def test_sendmail_inline_images_parameter_respected(self):
+ """Test that inline_images parameter works through sendmail."""
+
+ test_image_content = b"FAKE_PNG_BINARY_CONTENT_FOR_TESTING"
+
+ html_content = '