From 652030d1621deecf723f78134962917fe1e9b2bc Mon Sep 17 00:00:00 2001 From: Alex Wieser Date: Mon, 3 Mar 2025 17:25:44 +0100 Subject: [PATCH 1/2] Wrap header values in quotes if they contain characters that are not allowed --- lib/mail/renderers/rfc_2822.ex | 9 +++++++++ test/mail/renderers/rfc_2822_test.exs | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/mail/renderers/rfc_2822.ex b/lib/mail/renderers/rfc_2822.ex index d41fe280..c64463fe 100644 --- a/lib/mail/renderers/rfc_2822.ex +++ b/lib/mail/renderers/rfc_2822.ex @@ -140,6 +140,7 @@ defmodule Mail.Renderers.RFC2822 do defp render_address({name, email}), do: ~s("#{name}" <#{validate_address(email)}>) defp render_address(email), do: validate_address(email) + defp render_subtypes([]), do: [] defp render_subtypes([{key, value} | subtypes]) when is_atom(key), @@ -152,6 +153,14 @@ defmodule Mail.Renderers.RFC2822 do defp render_subtypes([{key, value} | subtypes]) do key = String.replace(key, "_", "-") value = encode_header_value(value, :quoted_printable) + + value = + if value =~ ~r/[\s;]/ do + "\"#{value}\"" + else + value + end + ["#{key}=#{value}" | render_subtypes(subtypes)] end diff --git a/test/mail/renderers/rfc_2822_test.exs b/test/mail/renderers/rfc_2822_test.exs index 3c928c0a..cc518960 100644 --- a/test/mail/renderers/rfc_2822_test.exs +++ b/test/mail/renderers/rfc_2822_test.exs @@ -15,6 +15,17 @@ defmodule Mail.Renderers.RFC2822Test do assert header == "Foo-Bar: abcd; baz-buzz=qux" end + test "quotes header parameters if necessary" do + header = Mail.Renderers.RFC2822.render_header("Content-Disposition", ["attachment", filename: "my-test-file"]) + assert header == "Content-Disposition: attachment; filename=my-test-file" + + header = Mail.Renderers.RFC2822.render_header("Content-Disposition", ["attachment", filename: "my test file"]) + assert header == "Content-Disposition: attachment; filename=\"my test file\"" + + header = Mail.Renderers.RFC2822.render_header("Content-Disposition", ["attachment", filename: "my;test;file"]) + assert header == "Content-Disposition: attachment; filename=\"my;test;file\"" + end + test "address headers renders list of recipients" do header = Mail.Renderers.RFC2822.render_header("from", "user1@example.com") assert header == "From: user1@example.com" From e642e20050af93c32e39a20c839334d5569d5b98 Mon Sep 17 00:00:00 2001 From: Alex Wieser Date: Tue, 18 Mar 2025 12:00:09 +0100 Subject: [PATCH 2/2] Consider all characters mentioned by RFC2822 --- lib/mail/renderers/rfc_2822.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mail/renderers/rfc_2822.ex b/lib/mail/renderers/rfc_2822.ex index c64463fe..d56a4d1a 100644 --- a/lib/mail/renderers/rfc_2822.ex +++ b/lib/mail/renderers/rfc_2822.ex @@ -155,7 +155,7 @@ defmodule Mail.Renderers.RFC2822 do value = encode_header_value(value, :quoted_printable) value = - if value =~ ~r/[\s;]/ do + if value =~ ~r/[\s()<>@,;:\\<\/\[\]?=]/ do "\"#{value}\"" else value