diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 4727518dd..bda4d6e67 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -24,6 +24,7 @@ Bug Fixes: * Regression: Preserve message-level charset when adding parts (related to Rails ActionMailer) @shields * Regression: Adding a part should not reset the mail's charset to nil @railsbob +* Fix exception when multibyte UTF-8 chars are in multipart boundary @pdg137 Performance: diff --git a/lib/mail/body.rb b/lib/mail/body.rb index ca763c416..c7ae4bb4a 100644 --- a/lib/mail/body.rb +++ b/lib/mail/body.rb @@ -269,13 +269,20 @@ def default_encoding # split parts by boundary, ignore first part if empty, append final part when closing boundary was missing def extract_parts + clean_boundary = boundary || "" + if raw_source.encoding == Encoding::ASCII_8BIT && + clean_boundary.encoding == Encoding::UTF_8 + clean_boundary.force_encoding(Encoding::ASCII_8BIT) + end + clean_boundary = Regexp.escape(boundary || "") + parts_regex = / (?: # non-capturing group \A | # start of string OR \r?\n # line break with optional CR ) ( - --#{Regexp.escape(boundary || "")} # boundary delimiter + --#{clean_boundary} # boundary delimiter (?:--)? # with non-capturing optional closing ) (?=\s*$) # lookahead matching zero or more spaces followed by line-ending diff --git a/spec/fixtures/emails/error_emails/utf8_multipart_boundary.eml b/spec/fixtures/emails/error_emails/utf8_multipart_boundary.eml new file mode 100644 index 000000000..39417251a --- /dev/null +++ b/spec/fixtures/emails/error_emails/utf8_multipart_boundary.eml @@ -0,0 +1,7 @@ +Content-Type: multipart/alternative; boundary="bad-char-µ" + +--bad-char-µ +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Hello, world! diff --git a/spec/mail/example_emails_spec.rb b/spec/mail/example_emails_spec.rb index a2559bdc8..c74642106 100644 --- a/spec/mail/example_emails_spec.rb +++ b/spec/mail/example_emails_spec.rb @@ -392,5 +392,10 @@ expect(mail.encoded).to include("Subject: =?UTF-8?Q?Forma=E7=E3o_FrenetikPolis:_Mega_Campanha_Final?=\r\n =?UTF-8?Q?_Ver=E3o_|_Cursos_de_Setembro?=") end end + + it 'does not fail on UTF-8 in multipart boundary' do + mail = read_fixture('emails', 'error_emails', 'utf8_multipart_boundary.eml') + expect(mail.parts.length).to eq(1) + end end end