diff --git a/lib/email/sender.rb b/lib/email/sender.rb index f5b3c4bb706..027d85893c7 100644 --- a/lib/email/sender.rb +++ b/lib/email/sender.rb @@ -332,8 +332,11 @@ module Email content = Mail::Part.new do content_type "multipart/alternative" - part html_part - part text_part + # we have to re-specify the charset and give the part the decoded body + # here otherwise the parts will get encoded with US-ASCII which makes + # a bunch of characters not render correctly in the email + part content_type: "text/html; charset=utf-8", body: html_part.body.decoded + part content_type: "text/plain; charset=utf-8", body: text_part.body.decoded end @message.parts.unshift(content) diff --git a/spec/components/email/sender_spec.rb b/spec/components/email/sender_spec.rb index 54b30ceca83..d3c7741c4f5 100644 --- a/spec/components/email/sender_spec.rb +++ b/spec/components/email/sender_spec.rb @@ -378,7 +378,7 @@ describe Email::Sender do fab!(:post) { Fabricate(:post) } fab!(:reply) do raw = <<~RAW - Hello world! + Hello world! It’s a great day! #{UploadMarkdown.new(small_pdf).attachment_markdown} #{UploadMarkdown.new(large_pdf).attachment_markdown} #{UploadMarkdown.new(image).image_markdown} @@ -460,6 +460,13 @@ describe Email::Sender do expect(message.html_part.body).to include("embedded-secure-image") expect(message.attachments.length).to eq(4) end + + it "uses correct UTF-8 encoding for the body of the email" do + Email::Sender.new(message, :valid_type).send + expect(message.html_part.body).not_to include("Itâ\u0080\u0099s") + expect(message.html_part.body).to include("It’s") + expect(message.html_part.charset.downcase).to eq("utf-8") + end end end @@ -491,6 +498,13 @@ describe Email::Sender do expect(message.parts[0].content_type).to start_with("multipart/alternative") expect(message.parts[0].parts.size).to eq(2) end + + it "uses correct UTF-8 encoding for the body of the email" do + Email::Sender.new(message, :valid_type).send + expect(message.html_part.body).not_to include("Itâ\u0080\u0099s") + expect(message.html_part.body).to include("It’s") + expect(message.html_part.charset.downcase).to eq("utf-8") + end end context 'with a deleted post' do