Skip to content

Commit 11fb848

Browse files
committedMar 17, 2025·
Fix parsing of structured headers with invalid params
1 parent 499e2eb commit 11fb848

File tree

2 files changed

+40
-31
lines changed

2 files changed

+40
-31
lines changed
 

‎lib/mail/parsers/rfc_2822.ex

+38-26
Original file line numberDiff line numberDiff line change
@@ -486,51 +486,63 @@ defmodule Mail.Parsers.RFC2822 do
486486
acc \\ ""
487487
)
488488

489-
defp parse_structured_header_value("", value, [{key, nil} | sub_types], _part, acc),
490-
do: [value | Enum.reverse([{key, acc} | sub_types])]
489+
defp parse_structured_header_value("", value, [{key, nil} | sub_types], _part, acc) do
490+
[value | Enum.reverse([{key, acc} | sub_types])]
491+
end
491492

492-
defp parse_structured_header_value("", nil, [], _part, acc),
493-
do: acc
493+
defp parse_structured_header_value("", value, sub_types, :param_name, _acc) do
494+
[value | Enum.reverse(sub_types)]
495+
end
494496

495-
defp parse_structured_header_value("", value, sub_types, _part, ""),
496-
do: [value | Enum.reverse(sub_types)]
497+
defp parse_structured_header_value("", nil, [], _part, acc) do
498+
acc
499+
end
497500

498-
defp parse_structured_header_value("", value, [], _part, acc),
499-
do: [value, String.trim(acc)]
501+
defp parse_structured_header_value("", value, [_ | _] = sub_types, _part, "") do
502+
[value | Enum.reverse(sub_types)]
503+
end
500504

501-
defp parse_structured_header_value("", value, sub_types, part, acc),
502-
do: parse_structured_header_value("", value, sub_types, part, String.trim(acc))
505+
defp parse_structured_header_value("", value, [], _part, acc) do
506+
[value, String.trim(acc)]
507+
end
508+
509+
defp parse_structured_header_value("", value, sub_types, part, acc) do
510+
parse_structured_header_value("", value, sub_types, part, String.trim(acc))
511+
end
503512

504513
defp parse_structured_header_value(<<"\"", rest::binary>>, value, sub_types, part, acc) do
505514
{string, rest} = parse_quoted_string(rest)
506515
parse_structured_header_value(rest, value, sub_types, part, <<acc::binary, string::binary>>)
507516
end
508517

509518
defp parse_structured_header_value(<<";", rest::binary>>, nil, sub_types, part, acc)
510-
when part in [:value, :param_value],
511-
do: parse_structured_header_value(rest, acc, sub_types, :param_name, "")
519+
when part in [:value, :param_value] do
520+
parse_structured_header_value(rest, acc, sub_types, :param_name, "")
521+
end
512522

513523
defp parse_structured_header_value(
514524
<<";", rest::binary>>,
515525
value,
516526
[{key, nil} | sub_types],
517527
:param_value,
518528
acc
519-
),
520-
do: parse_structured_header_value(rest, value, [{key, acc} | sub_types], :param_name, "")
529+
) do
530+
parse_structured_header_value(rest, value, [{key, acc} | sub_types], :param_name, "")
531+
end
521532

522-
defp parse_structured_header_value(<<"=", rest::binary>>, value, sub_types, :param_name, acc),
523-
do:
524-
parse_structured_header_value(
525-
rest,
526-
value,
527-
[{key_to_atom(acc), nil} | sub_types],
528-
:param_value,
529-
""
530-
)
531-
532-
defp parse_structured_header_value(<<char::utf8, rest::binary>>, value, sub_types, part, acc),
533-
do: parse_structured_header_value(rest, value, sub_types, part, <<acc::binary, char::utf8>>)
533+
defp parse_structured_header_value(<<"=", rest::binary>>, value, sub_types, :param_name, acc) do
534+
parse_structured_header_value(
535+
rest,
536+
value,
537+
[{key_to_atom(acc), nil} | sub_types],
538+
:param_value,
539+
""
540+
)
541+
end
542+
543+
defp parse_structured_header_value(<<char::utf8, rest::binary>>, value, sub_types, part, acc) do
544+
parse_structured_header_value(rest, value, sub_types, part, <<acc::binary, char::utf8>>)
545+
end
534546

535547
defp parse_quoted_string(string, acc \\ "")
536548

‎test/mail/parsers/rfc_2822_test.exs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1024,9 +1024,6 @@ defmodule Mail.Parsers.RFC2822Test do
10241024
assert message.headers["subject"] == "Test of new header generator"
10251025
end
10261026

1027-
defp parse_email(email, opts \\ []),
1028-
do: email |> convert_crlf |> Mail.Parsers.RFC2822.parse(opts)
1029-
10301027
test "invalid content-type should not take infinite time" do
10311028
message =
10321029
parse_email("""
@@ -1036,8 +1033,8 @@ defmodule Mail.Parsers.RFC2822Test do
10361033
assert message.headers["content-type"] == ["text/html", {"charset", "us-ascii"}]
10371034
end
10381035

1039-
defp parse_email(email),
1040-
do: email |> convert_crlf |> Mail.Parsers.RFC2822.parse()
1036+
defp parse_email(email, opts \\ []),
1037+
do: email |> convert_crlf |> Mail.Parsers.RFC2822.parse(opts)
10411038

10421039
defp parse_recipient(recipient),
10431040
do: Mail.Parsers.RFC2822.parse_recipient_value(recipient)

0 commit comments

Comments
 (0)
Please sign in to comment.