Skip to content

Commit

Permalink
Change doc examples to doctests to fix inconsistencies
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtimberlake committed Oct 5, 2024
1 parent 68f4aa1 commit 66b88c5
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 85 deletions.
69 changes: 39 additions & 30 deletions lib/mail.ex
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ defmodule Mail do
end)
end

def get_text(%Mail.Message{headers: %{"content-type" => "text/plain" <> _}} = message),
do: message

def get_text(%Mail.Message{headers: %{"content-type" => ["text/plain" | _]}} = message),
do: message

Expand Down Expand Up @@ -261,8 +258,10 @@ defmodule Mail do
@doc """
Add a new `subject` header
Mail.put_subject(%Mail.Message{}, "Welcome to DockYard!")
%Mail.Message{headers: %{subject: "Welcome to DockYard!"}}
## Examples
iex> Mail.put_subject(%Mail.Message{}, "Welcome to DockYard!")
%Mail.Message{headers: %{"subject" => "Welcome to DockYard!"}}
"""
def put_subject(message, subject),
do: Mail.Message.put_header(message, "subject", subject)
Expand All @@ -279,15 +278,17 @@ defmodule Mail do
Recipients can be added as a single string or a list of strings.
The list of recipients will be concated to the previous value.
Mail.put_to(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{to: ["[email protected]"]}}
## Examples
iex> Mail.put_to(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{"to" => ["[email protected]"]}}
Mail.put_to(%Mail.Message{}, ["[email protected]", "[email protected]"])
%Mail.Message{headers: %{to: ["[email protected]", "[email protected]"]}}
iex> Mail.put_to(%Mail.Message{}, ["[email protected]", "[email protected]"])
%Mail.Message{headers: %{"to" => ["[email protected]", "[email protected]"]}}
Mail.put_to(%Mail.Message{}, "[email protected]")
|> Mail.put_to(["[email protected]", "[email protected]"])
%Mail.Message{headers: %{to: ["[email protected]", "[email protected]", "[email protected]"]}}
iex> Mail.put_to(%Mail.Message{}, "[email protected]")
iex> |> Mail.put_to(["[email protected]", "[email protected]"])
%Mail.Message{headers: %{"to" => ["[email protected]", "[email protected]", "[email protected]"]}}
The value of a recipient must conform to either a string value or a tuple with two elements,
otherwise an `ArgumentError` is raised.
Expand Down Expand Up @@ -319,15 +320,17 @@ defmodule Mail do
Recipients can be added as a single string or a list of strings.
The list of recipients will be concated to the previous value.
Mail.put_cc(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{cc: ["[email protected]"]}}
## Examples
Mail.put_cc(%Mail.Message{}, ["[email protected]", "[email protected]"])
%Mail.Message{headers: %{cc: ["one@example.com", "two@example.com"]}}
iex> Mail.put_cc(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{"cc" => ["[email protected]"]}}
Mail.put_cc(%Mail.Message{}, "[email protected]")
|> Mail.put_cc(["[email protected]", "[email protected]"])
%Mail.Message{headers: %{cc: ["[email protected]", "[email protected]", "[email protected]"]}}
iex> Mail.put_cc(%Mail.Message{}, ["[email protected]", "[email protected]"])
%Mail.Message{headers: %{"cc" => ["[email protected]", "[email protected]"]}}
iex> Mail.put_cc(%Mail.Message{}, "[email protected]")
iex> |> Mail.put_cc(["[email protected]", "[email protected]"])
%Mail.Message{headers: %{"cc" => ["[email protected]", "[email protected]", "[email protected]"]}}
The value of a recipient must conform to either a string value or a tuple with two elements,
otherwise an `ArgumentError` is raised.
Expand Down Expand Up @@ -359,15 +362,17 @@ defmodule Mail do
Recipients can be added as a single string or a list of strings.
The list of recipients will be concated to the previous value.
Mail.put_bcc(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{bcc: ["[email protected]"]}}
## Examples
iex> Mail.put_bcc(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{"bcc" => ["[email protected]"]}}
Mail.put_bcc(%Mail.Message{}, ["[email protected]", "[email protected]"])
%Mail.Message{headers: %{bcc: ["[email protected]", "[email protected]"]}}
iex> Mail.put_bcc(%Mail.Message{}, ["[email protected]", "[email protected]"])
%Mail.Message{headers: %{"bcc" => ["[email protected]", "[email protected]"]}}
Mail.put_bcc(%Mail.Message{}, "[email protected]")
|> Mail.put_bcc(["[email protected]", "[email protected]"])
%Mail.Message{headers: %{bcc: ["[email protected]", "[email protected]", "[email protected]"]}}
iex> Mail.put_bcc(%Mail.Message{}, "[email protected]")
iex> |> Mail.put_bcc(["[email protected]", "[email protected]"])
%Mail.Message{headers: %{"bcc" => ["[email protected]", "[email protected]", "[email protected]"]}}
The value of a recipient must conform to either a string value or a tuple with two elements,
otherwise an `ArgumentError` is raised.
Expand Down Expand Up @@ -396,8 +401,10 @@ defmodule Mail do
@doc """
Add a new `from` header
Mail.put_from(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{from: "[email protected]"}}
## Examples
iex> Mail.put_from(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{"from" => "[email protected]"}}
"""
def put_from(message, sender),
do: Mail.Message.put_header(message, "from", sender)
Expand All @@ -411,8 +418,10 @@ defmodule Mail do
@doc """
Add a new `reply-to` header
Mail.put_reply_to(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{reply_to: "[email protected]"}}
## Examples
iex> Mail.put_reply_to(%Mail.Message{}, "[email protected]")
%Mail.Message{headers: %{"reply-to" => "[email protected]"}}
"""
def put_reply_to(message, reply_address),
do: Mail.Message.put_header(message, "reply-to", reply_address)
Expand Down
119 changes: 79 additions & 40 deletions lib/mail/message.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ defmodule Mail.Message do
@doc """
Add new part
Mail.Message.put_part(%Mail.Message{}, %Mail.Message{})
## Examples
iex> Mail.Message.put_part(%Mail.Message{}, %Mail.Message{})
%Mail.Message{parts: [%Mail.Message{}]}
"""
def put_part(message, %Mail.Message{} = part) do
put_in(message.parts, message.parts ++ [part])
Expand All @@ -27,10 +30,14 @@ defmodule Mail.Message do
@doc """
Will match on a full or partial content type
Mail.Message.match_content_type?(message, ~r/text/)
## Examples
iex> message = %Mail.Message{headers: %{"content-type" => ["text/plain", {"charset", "UTF-8"}]}}
iex> Mail.Message.match_content_type?(message, ~r/text/)
true
Mail.Message.match_content_type?(message, "text/html")
iex> message = %Mail.Message{headers: %{"content-type" => ["text/plain", {"charset", "UTF-8"}]}}
iex> Mail.Message.match_content_type?(message, "text/html")
false
"""
def match_content_type?(message, string_or_regex)
Expand All @@ -52,7 +59,10 @@ defmodule Mail.Message do
@doc """
Add a new header key/value pair
Mail.Message.put_header(%Mail.Message{}, :content_type, "text/plain")
## Examples
iex> Mail.Message.put_header(%Mail.Message{}, :content_type, "text/plain")
%Mail.Message{headers: %{"content-type" => "text/plain"}}
The individual headers will be in the `headers` field on the
`%Mail.Message{}` struct
Expand All @@ -72,7 +82,9 @@ defmodule Mail.Message do
@doc """
Deletes a specific header key
Mail.Message.delete_header(%Mail.Message{headers: %{foo: "bar"}}, :foo)
## Examples
iex> Mail.Message.delete_header(%Mail.Message{headers: %{"foo" => "bar"}}, :foo)
%Mail.Message{headers: %{}}
"""
def delete_header(message, header),
Expand All @@ -81,7 +93,9 @@ defmodule Mail.Message do
@doc """
Deletes a list of headers
Mail.Message.delete_headers(%Mail.Message{headers: %{foo: "bar", baz: "qux"}}, [:foo, :baz])
## Examples
iex> Mail.Message.delete_headers(%Mail.Message{headers: %{"foo" => "bar", "baz" => "qux"}}, [:foo, :baz])
%Mail.Message{headers: %{}}
"""
def delete_headers(message, headers)
Expand All @@ -104,24 +118,35 @@ defmodule Mail.Message do
The value will always be wrapped in a `List`
Mail.Message.put_content_type(%Mail.Message{}, "text/plain")
%Mail.Message{headers: %{content_type: ["text/plain"]}}
## Examples
iex> Mail.Message.put_content_type(%Mail.Message{}, "text/plain")
%Mail.Message{headers: %{"content-type" => ["text/plain"]}}
iex> Mail.Message.put_content_type(%Mail.Message{}, ["text/plain", {"charset", "UTF-8"}])
%Mail.Message{headers: %{"content-type" => ["text/plain", {"charset", "UTF-8"}]}}
"""
def put_content_type(message, content_type),
do: put_header(message, :content_type, content_type)
def put_content_type(message, content_type) when is_binary(content_type),
do: put_content_type(message, [content_type])

def put_content_type(message, content_type) do
put_header(message, :content_type, content_type)
end

@doc """
Gets the `content_type` from the header
Will ensure the `content_type` is always wrapped in a `List`
Mail.Message.get_content_type(%Mail.Message{})
## Examples
iex> Mail.Message.get_content_type(%Mail.Message{})
[""]
Mail.Message.get_content_type(%Mail.Message{content_type: "text/plain"})
iex> Mail.Message.get_content_type(%Mail.Message{headers: %{"content-type" => "text/plain"}})
["text/plain"]
Mail.Message.get_content_type(%Mail.Message{headers: %{content_type: ["multipart/mixed", {"boundary", "foobar"}]}})
iex> Mail.Message.get_content_type(%Mail.Message{headers: %{"content-type" => ["multipart/mixed", {"boundary", "foobar"}]}})
["multipart/mixed", {"boundary", "foobar"}]
"""
def get_content_type(message),
Expand All @@ -135,11 +160,13 @@ defmodule Mail.Message do
Will overwrite existing `boundary` key in the list. Will preserve other
values in the list
Mail.Message.put_boundary(%Mail.Message{}, "foobar")
%Mail.Message{headers: %{content_type: ["", {"boundary", "foobar"}]}}
## Examples
iex> Mail.Message.put_boundary(%Mail.Message{}, "foobar")
%Mail.Message{headers: %{"content-type" => ["", {"boundary", "foobar"}]}}
Mail.Message.put_boundary(%Mail.Message{headers: %{content_type: ["multipart/mixed", {"boundary", "bazqux"}]}})
%Mail.Message{headers: %{content_type: ["multipart/mixed", {"boundary", "foobar"}]}}
iex> Mail.Message.put_boundary(%Mail.Message{headers: %{"content-type" => ["multipart/mixed", {"boundary", "bazqux"}]}}, "foobar")
%Mail.Message{headers: %{"content-type" => ["multipart/mixed", {"boundary", "foobar"}]}}
"""
def put_boundary(message, boundary) do
content_type =
Expand All @@ -154,10 +181,12 @@ defmodule Mail.Message do
Will retrieve the boundary value. If one is not set a random one is generated.
Mail.Message.get_boundary(%Mail.Message{headers: %{content_type: ["multipart/mixed", {"boundary", "foobar"}]}})
## Examples
iex> Mail.Message.get_boundary(%Mail.Message{headers: %{"content-type" => ["multipart/mixed", {"boundary", "foobar"}]}})
"foobar"
Mail.Message.get_boundary(%Mail.Message{headers: %{content_type: ["multipart/mixed"]}})
iex> Mail.Message.get_boundary(%Mail.Message{headers: %{"content-type" => ["multipart/mixed", {"boundary", "ASDFSHNEW3473423"}]}})
"ASDFSHNEW3473423"
"""
def get_boundary(message) do
Expand All @@ -177,7 +206,9 @@ defmodule Mail.Message do
@doc """
Sets the `body` field on the part
Mail.Message.put_body(%Mail.Message{}, "Some data")
## Examples
iex> Mail.Message.put_body(%Mail.Message{}, "Some Data")
%Mail.Message{body: "Some Data", headers: %{}}
"""
def put_body(part, body),
Expand All @@ -186,11 +217,13 @@ defmodule Mail.Message do
@doc """
Build a new text message
Mail.Message.build_text("Some text")
%Mail.Message{body: "Some text", headers: %{content_type: "text/plain"}}
## Examples
Mail.Message.build_text("Some text", charset: "UTF-8")
%Mail.Message{body: "Some text", headers: %{content_type: ["text/plain", {"charset", "UTF-8"}]}}
iex> Mail.Message.build_text("Some text")
%Mail.Message{body: "Some text", headers: %{"content-type" => ["text/plain", {"charset", "UTF-8"}], "content-transfer-encoding" => :quoted_printable}}
iex> Mail.Message.build_text("Some text", charset: "us-ascii")
%Mail.Message{body: "Some text", headers: %{"content-type" => ["text/plain", {"charset", "us-ascii"}], "content-transfer-encoding" => :quoted_printable}}
## Options
Expand All @@ -214,11 +247,13 @@ defmodule Mail.Message do
@doc """
Build a new HTML message
Mail.Message.build_html("<h1>Some HTML</h1>")
%Mail.Message{body: "<h1>Some HTML</h1>", headers: %{content_type: "text/html"}}
## Examples
iex> Mail.Message.build_html("<h1>Some HTML</h1>")
%Mail.Message{body: "<h1>Some HTML</h1>", headers: %{"content-type" => ["text/html", {"charset", "UTF-8"}], "content-transfer-encoding" => :quoted_printable}}
Mail.Message.build_html("<h1>Some HTML</h1>", charset: "UTF-8")
%Mail.Message{body: "<h1>Some HTML</h1>", headers: %{content_type: ["text/html", {"charset", "UTF-8"}]}}
iex> Mail.Message.build_html("<h1>Some HTML</h1>", charset: "UTF-8")
%Mail.Message{body: "<h1>Some HTML</h1>", headers: %{"content-type" => ["text/html", {"charset", "UTF-8"}], "content-transfer-encoding" => :quoted_printable}}
## Options
Expand Down Expand Up @@ -255,11 +290,13 @@ defmodule Mail.Message do
The mimetype of the file is determined by the file extension.
Mail.Message.build_attachment("README.md")
%Mail.Message{data: "base64 encoded", headers: %{content_type: ["text/x-markdown"], content_disposition: ["attachment", filename: "README.md"], content_transfer_encoding: :base64}}
## Examples
Mail.Message.build_attachment({"README.md", "file contents"})
%Mail.Message{data: "base64 encoded", headers: %{content_type: ["text/x-markdown"], content_disposition: ["attachment", filename: "README.md"], content_transfer_encoding: :base64}}
iex> message = Mail.Message.build_attachment("README.md")
%Mail.Message{body: <<"# Mail\\n", _::binary>>, headers: %{"content-type" => ["text/markdown"], "content-disposition" => ["attachment", {"filename", "README.md"}], "content-transfer-encoding" => :base64}} = message
iex> message = Mail.Message.build_attachment({"README.md", "file contents"})
%Mail.Message{body: "file contents", headers: %{"content-type" => ["text/markdown"], "content-disposition" => ["attachment", {"filename", "README.md"}], "content-transfer-encoding" => :base64}} = message
## Options
Expand Down Expand Up @@ -297,18 +334,20 @@ defmodule Mail.Message do
* `:headers` - Headers to be merged
## Examples
Mail.Message.put_attachment(%Mail.Message{}, "README.md")
%Mail.Message{data: "base64 encoded", headers: %{content_type: ["text/x-markdown"], content_disposition: ["attachment", filename: "README.md"], content_transfer_encoding: :base64}}
Mail.Message.put_attachment(%Mail.Message{}, {"README.md", "file contents"})
%Mail.Message{data: "base64 encoded", headers: %{content_type: ["text/x-markdown"], content_disposition: ["attachment", filename: "README.md"], content_transfer_encoding: :base64}}
iex> message = Mail.Message.put_attachment(%Mail.Message{}, "README.md")
%Mail.Message{body: <<"# Mail\\n", _::binary>>, headers: %{"content-type" => ["text/markdown"], "content-disposition" => ["attachment", {"filename", "README.md"}], "content-transfer-encoding" => :base64}} = message
iex> Mail.Message.put_attachment(%Mail.Message{}, {"README.md", "file contents"})
%Mail.Message{body: "file contents", headers: %{"content-type" => ["text/markdown"], "content-disposition" => ["attachment", {"filename", "README.md"}], "content-transfer-encoding" => :base64}}
### Adding custom headers
Mail.Message.put_attachment(%Mail.Message{}, "README.md", headers: [content_id: "attachment-id"])
%Mail.Message{data: "base64 encoded", headers: %{content_type: ["text/x-markdown"], content_disposition: ["attachment", filename: "README.md"], content_transfer_encoding: :base64, content_id: "attachment-id"}}
Mail.Message.put_attachment(%Mail.Message{}, {"README.md", data}, headers: [content_id: "attachment-id"])
%Mail.Message{data: "base64 encoded", headers: %{content_type: ["text/x-markdown"], content_disposition: ["attachment", filename: "README.md"], content_transfer_encoding: :base64, content_id: "attachment-id"}}
iex> message =Mail.Message.put_attachment(%Mail.Message{}, "README.md", headers: [content_id: "attachment-id"])
%Mail.Message{body: <<"# Mail\\n", _::binary>>, headers: %{"content-type" => ["text/markdown"], "content-disposition" => ["attachment", {"filename", "README.md"}], "content-transfer-encoding" => :base64, "content-id" => "attachment-id"}} = message
iex> message = Mail.Message.put_attachment(%Mail.Message{}, {"README.md", "file contents"}, headers: [content_id: "attachment-id"])
%Mail.Message{body: "file contents", headers: %{"content-type" => ["text/markdown"], "content-disposition" => ["attachment", {"filename", "README.md"}], "content-transfer-encoding" => :base64, "content-id" => "attachment-id"}} = message
"""
def put_attachment(message, path_or_file_tuple, opts \\ [])

Expand Down
Loading

0 comments on commit 66b88c5

Please sign in to comment.