FIX: Missing multipart/mixed boundary on emails (#27599)

Followup 96a0781bc1

When sending emails where secure uploads is enabled
and secure_uploads_allow_embed_images_in_emails is
true, we attach the images to the email, and we
do some munging with the final email so the structure
of the MIME parts looks like this:

```
multipart/mixed
  multipart/alternative
    text/plain
    text/html
  image/jpeg
  image/jpeg
  image/png
```

However, we were not specifying the `boundary` of the
`multipart/mixed` main content-type of the email, so
sometimes the email would come through appearing to
have an empty body with the entire thing attached as
one attachment, and some mail parsers considered the
entire email as the "epilogue" and/or "preamble".

This commit fixes the issue by specifying the boundary
in the content-type header per https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
This commit is contained in:
Martin Brennan 2024-06-25 13:43:10 +10:00 committed by GitHub
parent aa8773e659
commit a128ce5c4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 1 deletions

View File

@ -435,12 +435,18 @@ module Email
# Due to mail gem magic, @message.text_part and @message.html_part still
# refer to the same objects.
#
# Most imporantly, we need to specify the boundary for the multipart/mixed
# part of the email, otherwise we can end up with an email that appears to
# be empty with the entire body attached as a single attachment, and some
# mail parsers consider the entire email as a preamble/epilogue.
#
# c.f. https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
def fix_parts_after_attachments!
has_attachments = @message.attachments.present?
has_alternative_renderings = @message.html_part.present? && @message.text_part.present?
if has_attachments && has_alternative_renderings
@message.content_type = "multipart/mixed"
@message.content_type = "multipart/mixed; boundary=\"#{@message.body.boundary}\""
html_part = @message.html_part
@message.html_part = nil

View File

@ -681,6 +681,9 @@ RSpec.describe Email::Sender do
Email::Sender.new(summary, "digest").send
expect(summary.content_type).to eq(
"multipart/mixed; boundary=\"#{summary.body.boundary}\"",
)
expect(summary.attachments.map(&:filename)).to include(
*[@secure_image, @secure_image_2, @secure_image_3].map(&:original_filename),
)