Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/mail/encoders/base64.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ defmodule Mail.Encoders.Base64 do
defp add_line_breaks(<<head::binary-size(76), tail::binary>>),
do: [head, "\r\n" | add_line_breaks(tail)]

defp add_line_breaks(tail), do: [tail, "\r\n"]
defp add_line_breaks(tail), do: [tail]
end
19 changes: 11 additions & 8 deletions lib/mail/parsers/rfc_2822.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,21 @@ defmodule Mail.Parsers.RFC2822 do
|> parse_body(lines, opts)
end

def parse(content, opts),
do: content |> String.split("\r\n") |> Enum.map(&String.trim_trailing/1) |> parse(opts)
def parse(content, opts) do
content
|> String.trim_trailing("\r\n")
|> String.split("\r\n")
|> parse(opts)
end

defp extract_headers(list, headers \\ [])

defp extract_headers(["" | tail], headers),
do: [Enum.reverse(headers), tail]

defp extract_headers([], headers),
do: [Enum.reverse(headers), []]

defp extract_headers([<<" ", _::binary>> = folded_body | tail], [previous_header | headers]),
do: extract_headers(tail, [previous_header <> folded_body | headers])

Expand All @@ -86,6 +93,8 @@ defmodule Mail.Parsers.RFC2822 do
"""
@spec to_datetime(binary()) :: DateTime.t() | {:error, binary()}
def to_datetime(date_string) do
# Replace multiple spaces (or line breaks) with a single space
date_string = String.replace(date_string, ~r/\s+/m, " ")
parse_datetime(date_string)
rescue
_ -> {:error, date_string}
Expand Down Expand Up @@ -690,10 +699,6 @@ defmodule Mail.Parsers.RFC2822 do
end
end

defp parse_body(%Mail.Message{} = message, [], _opts) do
message
end

defp parse_body(%Mail.Message{} = message, lines, opts) do
decoded =
lines
Expand All @@ -705,7 +710,6 @@ defmodule Mail.Parsers.RFC2822 do

defp join_body(lines, acc \\ [])
defp join_body([], acc), do: acc |> Enum.reverse() |> Enum.join("\r\n")
defp join_body([""], acc), do: acc |> Enum.reverse() |> Enum.join("\r\n")
defp join_body([head | tail], acc), do: join_body(tail, [head | acc])

defp extract_parts(lines, boundary, acc \\ [], parts \\ nil)
Expand Down Expand Up @@ -831,7 +835,6 @@ defmodule Mail.Parsers.RFC2822 do
end

defp decode(body, message, opts) do
body = String.trim_trailing(body)
content_type = message.headers["content-type"]
charset = Mail.Proplist.get(content_type, "charset")
transfer_encoding = Mail.Message.get_header(message, "content-transfer-encoding")
Expand Down
2 changes: 1 addition & 1 deletion lib/mail/renderers/rfc_2822.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ defmodule Mail.Renderers.RFC2822 do

parts =
render_parts(message.parts, fun)
|> Enum.join("\r\n\r\n#{boundary}\r\n")
|> Enum.join("\r\n#{boundary}\r\n")

"#{headers}\r\n\r\n#{boundary}\r\n#{parts}\r\n#{boundary}--"
end
Expand Down
1 change: 0 additions & 1 deletion test/fixtures/recursive-part-rendering.eml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Hello there! 1 + 1 =3D 2

--foobar
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Expand Down
2 changes: 1 addition & 1 deletion test/mail/encoder_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ defmodule Mail.EncoderTest do

test "encodes a binary as base64" do
# with odd casings
assert "SGVsbG8sIFdvcmxk\r\n" == Encoder.encode("Hello, World", "BASE64")
assert "SGVsbG8sIFdvcmxk" == Encoder.encode("Hello, World", "BASE64")
assert "Hello, World" == Encoder.decode("SGVsbG8sIFdvcmxk\r\n", "Base64")
end

Expand Down
2 changes: 1 addition & 1 deletion test/mail/encoders/base64_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ defmodule Mail.Encoders.Base64Test do
encoded = Mail.Encoders.Base64.encode(message)

assert encoded ==
"SGVsbG8gd29ybGQhIEhlbGxvIHdvcmxkISBIZWxsbyB3b3JsZCEgSGVsbG8gd29ybGQhIEhlbGxv\r\nIHdvcmxkISBIZWxsbyB3b3JsZCEgSGVsbG8gd29ybGQhIEhlbGxvIHdvcmxkISBIZWxsbyB3b3Js\r\nZCE=\r\n"
"SGVsbG8gd29ybGQhIEhlbGxvIHdvcmxkISBIZWxsbyB3b3JsZCEgSGVsbG8gd29ybGQhIEhlbGxv\r\nIHdvcmxkISBIZWxsbyB3b3JsZCEgSGVsbG8gd29ybGQhIEhlbGxvIHdvcmxkISBIZWxsbyB3b3Js\r\nZCE="
end
end
15 changes: 4 additions & 11 deletions test/mail/parsers/rfc_2822_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ defmodule Mail.Parsers.RFC2822Test do
assert message.headers["from"] == "me@example.com"
assert message.headers["reply-to"] == "otherme@example.com"
assert message.headers["subject"] == "Test Email"
assert message.body == nil
assert message.body == ""
end

test "parses a multipart message" do
Expand Down Expand Up @@ -80,7 +80,7 @@ defmodule Mail.Parsers.RFC2822Test do
[text_part, html_part] = message.parts

assert text_part.headers["content-type"] == ["text/plain", {"charset", "us-ascii"}]
assert text_part.body == "This is some text"
assert text_part.body == "This is some text\r\n"

assert html_part.headers["content-type"] == ["text/html", {"charset", "us-ascii"}]
assert html_part.body == "<h1>This is some HTML</h1>"
Expand All @@ -101,12 +101,10 @@ defmodule Mail.Parsers.RFC2822Test do
Content-Type: text/plain

This is some text

--foobar
Content-Type: text/html

<h1>This is some HTML</h1>

--foobar
x-my-header: no body!

Expand All @@ -124,7 +122,7 @@ defmodule Mail.Parsers.RFC2822Test do
assert html_part.body == "<h1>This is some HTML</h1>"

assert headers_only_part.headers["x-my-header"] == "no body!"
assert headers_only_part.body == nil
assert headers_only_part.body == ""
end

# A reproduction of an email found in the wild.
Expand Down Expand Up @@ -381,7 +379,6 @@ defmodule Mail.Parsers.RFC2822Test do
Content-Type: text/html

<h1>This is the HTML</h1>

--bazqux--
--foobar
Content-Type: text/markdown
Expand Down Expand Up @@ -412,7 +409,7 @@ defmodule Mail.Parsers.RFC2822Test do
[text_part, html_part] = alt_part.parts

assert text_part.headers["content-type"] == ["text/plain", {"charset", "us-ascii"}]
assert text_part.body == "This is some text"
assert text_part.body == "This is some text\r\n"

assert html_part.headers["content-type"] == ["text/html", {"charset", "us-ascii"}]
assert html_part.body == "<h1>This is the HTML</h1>"
Expand Down Expand Up @@ -846,7 +843,6 @@ defmodule Mail.Parsers.RFC2822Test do
Content-Transfer-Encoding: quoted-printable

fran=E7aise pr=E8s =E0 th=E9=E2tre lumi=E8re

------=_Part_295474_20544590.1456382229928
Content-Type: application/octet-stream;
name="=?Windows-1252?Q?Imagin=E9.pdf?="
Expand All @@ -858,7 +854,6 @@ defmodule Mail.Parsers.RFC2822Test do
Content-Transfer-Encoding: base64

JVBERi0xLjcKJeLjz9MKNiAwIG9iago8PCAvQ3JlYXRvciAoT3BlblRleHQgRXhzdHJlYW0gVmVy

------=_Part_295474_20544590.1456382229928
Content-Type: application/pdf;
name="=?windows-1258?Q?Pre=ECsentation.pdf?="
Expand All @@ -871,7 +866,6 @@ defmodule Mail.Parsers.RFC2822Test do
Content-Transfer-Encoding: base64

JVBERi0xLjcKJeLjz9MKNiAwIG9iago8PCAvQ3JlYXRvciAoT3BlblRleHQgRXhzdHJlYW0gVmVy

------=_Part_295474_20544590.1456382229928
Content-Type: application/octet-stream;
name="=?Windows-1252?Q?ID_S=E9_-_Liste_inscrits.xlsx?="
Expand All @@ -883,7 +877,6 @@ defmodule Mail.Parsers.RFC2822Test do
Content-Transfer-Encoding: base64

JVBERi0xLjcKJeLjz9MKNiAwIG9iago8PCAvQ3JlYXRvciAoT3BlblRleHQgRXhzdHJlYW0gVmVy

------=_Part_295474_20544590.1456382229928
"""

Expand Down
4 changes: 2 additions & 2 deletions test/mail/renderers/rfc_2822_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ defmodule Mail.Renderers.RFC2822Test do
|> Mail.put_from({"User2", "user2@example.com"})
|> Mail.put_reply_to({"User3", "user3@example.com"})
|> Mail.put_subject("Test email")
|> Mail.put_text("Some text")
|> Mail.put_text("Some text\r\n")
|> Mail.put_html("<h1>Some HTML</h1>")
|> Mail.Message.put_content_type("multipart/alternative")
|> Mail.Message.put_boundary("foobar")
Expand All @@ -238,7 +238,7 @@ defmodule Mail.Renderers.RFC2822Test do
|> Mail.put_to("user1@example.com")
|> Mail.put_from({"User2", "user2@example.com"})
|> Mail.put_subject("Test email")
|> Mail.put_text("Some text")
|> Mail.put_text("Some text\r\n")
|> Mail.put_html("<h1>Some HTML</h1>")
|> Mail.put_attachment({"tiny_jpeg.jpg", @tiny_jpeg_binary})

Expand Down