Skip to content

Commit

Permalink
Use a fake smtp server for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aellispierce committed Apr 26, 2016
1 parent 3e4178d commit 9b2eca1
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 124 deletions.
2 changes: 1 addition & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ config :logger, level: :warn
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env}.exs"
import_config "#{Mix.env}.exs"
4 changes: 4 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use Mix.Config

config :bamboo,
smtp_client: Bamboo.SmtpAdapterTest.FakeSmtp
4 changes: 4 additions & 0 deletions config/prod.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use Mix.Config

config :bamboo,
smtp_client: :gen_smtp_client
6 changes: 6 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use Mix.Config

config :logger, level: :warn

config :bamboo,
smtp_client: Bamboo.SmtpAdapterTest.FakeSmtp
1 change: 0 additions & 1 deletion lib/bamboo/adapters/mandrill_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ defmodule Bamboo.MandrillAdapter do
#{inspect response, limit: :infinity}
Here are the params we sent:
#{inspect filtered_params, limit: :infinity}
Expand Down
1 change: 0 additions & 1 deletion lib/bamboo/adapters/sendgrid_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ defmodule Bamboo.SendgridAdapter do
#{inspect response, limit: :infinity}
Here are the params we sent:
#{inspect filtered_params, limit: :infinity}
Expand Down
25 changes: 17 additions & 8 deletions lib/bamboo/adapters/smtp_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,40 @@ defmodule Bamboo.SmtpAdapter do
Sends email using SMTP.
"""
@behaviour Bamboo.Adapter
@client Application.get_env(:bamboo, :smtp_client)

alias Bamboo.Email

def deliver(email, config) do
get_domain(config)
get_relay(config)
format_email(email, config)
|> @client.send(config)
end

def handle_config(config) do
if Map.get(config, :domain) do
if Map.get(config, :relay) do
config
else
raise_domain_error(config)
raise_relay_error(config)
end
end

defp get_domain(config) do
case Map.get(config, :domain) do
nil -> raise_domain_error(config)
def format_email(email, config) do
config = Enum.into(config, [])
from_address = Email.get_address(email.from)
{from_address, email.to, email.text_body}
end

defp get_relay(config) do
case Map.get(config, :relay) do
nil -> raise_relay_error(config)
key -> key
end
end

defp raise_domain_error(config) do
defp raise_relay_error(config) do
raise ArgumentError, """
There was no domain set for the Smtp adapter.
There was no relay set for the Smtp adapter.
* Here are the config options that were passed in:
Expand Down
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ defmodule Bamboo.Mixfile do
{:earmark, ">= 0.0.0", only: :dev},
{:httpoison, "~> 0.8"},
{:poison, ">= 1.5.0"},
{:gen_smtp, "~> 0.9.0"},
]
end
end
8 changes: 7 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%{"certifi": {:hex, :certifi, "0.3.0"},
"combine": {:hex, :combine, "0.7.0"},
"cowboy": {:hex, :cowboy, "1.0.4"},
"cowlib": {:hex, :cowlib, "1.0.2"},
"earmark": {:hex, :earmark, "0.2.1"},
Expand All @@ -7,15 +8,20 @@
"excoveralls": {:hex, :excoveralls, "0.5.1"},
"exjsx": {:hex, :exjsx, "3.2.0"},
"floki": {:hex, :floki, "0.8.0"},
"gen_smtp": {:hex, :gen_smtp, "0.9.0"},
"gettext": {:hex, :gettext, "0.11.0"},
"hackney": {:hex, :hackney, "1.4.8"},
"httpoison": {:hex, :httpoison, "0.8.1"},
"idna": {:hex, :idna, "1.0.3"},
"jsx": {:hex, :jsx, "2.6.2"},
"mailer": {:git, "https://github.com/antp/mailer.git", "9f62bec0b9d2b618c91646066f604bd6b67fac40", []},
"mimerl": {:hex, :mimerl, "1.0.2"},
"mochiweb_html": {:hex, :mochiweb_html, "2.13.0"},
"phoenix": {:hex, :phoenix, "1.1.4"},
"phoenix_html": {:hex, :phoenix_html, "2.2.0"},
"plug": {:hex, :plug, "1.1.2"},
"poison": {:hex, :poison, "2.1.0"},
"ranch": {:hex, :ranch, "1.2.1"},
"ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"}}
"ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"},
"timex": {:hex, :timex, "2.1.4"},
"tzdata": {:hex, :tzdata, "0.5.7"}}
168 changes: 56 additions & 112 deletions test/lib/bamboo/adapters/smtp_adapter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,143 +4,87 @@ defmodule Bamboo.SmtpAdapterTest do
alias Bamboo.SmtpHelper
alias Bamboo.SmtpAdapter

@config %{adapter: SmtpAdapter, domain: "www.example.com"}
@config %{adapter: SmtpAdapter, relay: "www.example.com"}
@bad_config %{adapter: SmtpAdapter}

defmodule FakeSmtp do
use Plug.Router

plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Poison
plug :match
plug :dispatch

def start_server(parent) do
Agent.start_link(fn -> HashDict.new end, name: __MODULE__)
Agent.update(__MODULE__, &HashDict.put(&1, :parent, parent))
port = get_free_port
Application.put_env(:bamboo, :smtp_base_uri, "http://localhost:#{port}")
Plug.Adapters.Cowboy.http __MODULE__, [], port: port, ref: __MODULE__
end
defstruct from: "",
to: "",
content: ""

defp get_free_port do
{:ok, socket} = :ranch_tcp.listen(port: 0)
{:ok, port} = :inet.port(socket)
:erlang.port_close(socket)
port
def start() do
Agent.start_link(fn -> [] end, name: __MODULE__)
end

def shutdown do
Plug.Adapters.Cowboy.shutdown __MODULE__
def clear do
Agent.update(__MODULE__, fn(_state) -> [] end)
end

post "/api/1.0/messages/send.json" do
case get_in(conn.params, ["message", "from_email"]) do
"INVALID_EMAIL" -> conn |> send_resp(500, "Error!!") |> send_to_parent
_ -> conn |> send_resp(200, "SENT") |> send_to_parent
end
def send({from, to, composed_email}, config) do
mail_data = %FakeSmtp{
from: from,
to: to,
content: composed_email
}

Agent.update(__MODULE__, fn(state) -> [mail_data | state] end)
end

defp send_to_parent(conn) do
parent = Agent.get(__MODULE__, fn(set) -> HashDict.get(set, :parent) end)
send parent, {:fake_smtp, conn}
conn
def get_mails do
Agent.get(__MODULE__, fn(state) -> state end)
end
end

setup do
FakeSmtp.start_server(self)

on_exit fn ->
FakeSmtp.shutdown
end
FakeSmtp.start

:ok
end

test "raises if the domain is nil" do
assert_raise ArgumentError, ~r/no domain set/, fn ->
test "raises if the relay is nil" do
assert_raise ArgumentError, ~r/no relay set/, fn ->
new_email(from: "foo@bar.com") |> SmtpAdapter.deliver(@bad_config)
end

assert_raise ArgumentError, ~r/no domain set/, fn ->
assert_raise ArgumentError, ~r/no relay set/, fn ->
SmtpAdapter.handle_config(%{})
end
end

# test "deliver/2 sends the to the right url" do
# new_email |> SmtpAdapter.deliver(@config)
#
# assert_receive {:fake_smtp, %{request_path: request_path}}
#
# assert request_path == "/api/1.0/messages/send.json"
# end
#
# test "deliver/2 sends from, html and text body, subject, and headers" do
# email = new_email(
# from: {"From", "from@foo.com"},
# subject: "My Subject",
# text_body: "TEXT BODY",
# html_body: "HTML BODY",
# )
# |> Email.put_header("Reply-To", "reply@foo.com")
#
# email |> SmtpAdapter.deliver(@config)
#
# assert_receive {:fake_smtp, %{params: params}}
# assert params["key"] == @config[:api_key]
# message = params["message"]
# assert message["from_name"] == email.from |> elem(0)
# assert message["from_email"] == email.from |> elem(1)
# assert message["subject"] == email.subject
# assert message["text"] == email.text_body
# assert message["html"] == email.html_body
# assert message["headers"] == email.headers
# end
#
# test "deliver/2 correctly formats recipients" do
# email = new_email(
# to: [{"To", "to@bar.com"}],
# cc: [{"CC", "cc@bar.com"}],
# bcc: [{"BCC", "bcc@bar.com"}],
# )
#
# email |> SmtpAdapter.deliver(@config)
#
# assert_receive {:fake_smtp, %{params: %{"message" => message}}}
# assert message["to"] == [
# %{"name" => "To", "email" => "to@bar.com", "type" => "to"},
# %{"name" => "CC", "email" => "cc@bar.com", "type" => "cc"},
# %{"name" => "BCC", "email" => "bcc@bar.com", "type" => "bcc"}
# ]
# end
#
# test "deliver/2 adds extra params to the message " do
# email = new_email |> SmtpHelper.put_param("important", true)
#
# email |> SmtpAdapter.deliver(@config)
#
# assert_receive {:fake_smtp, %{params: %{"message" => message}}}
# assert message["important"] == true
# end
#
# test "raises if the response is not a success" do
# email = new_email(from: "INVALID_EMAIL")
#
# assert_raise Bamboo.SmtpAdapter.ApiError, fn ->
# email |> SmtpAdapter.deliver(@config)
# end
# end
#
# test "removes api key from error output" do
# email = new_email(from: "INVALID_EMAIL")
#
# assert_raise Bamboo.SmtpAdapter.ApiError, ~r/"key" => "\[FILTERED\]"/, fn ->
# email |> SmtpAdapter.deliver(@config)
# end
# end
test "deliver/2 sends an email" do
new_email |> SmtpAdapter.deliver(@config)

assert length(FakeSmtp.get_mails) == 1
end

test "deliver/2 sends from, html and text body, subject, and headers" do
email = new_email(
from: {"From", "from@foo.com"},
subject: "My Subject",
text_body: "TEXT BODY",
html_body: "HTML BODY",
)
|> Email.put_header("Reply-To", "reply@foo.com")

email |> SmtpAdapter.deliver(@config)

assert length(FakeSmtp.get_mails) == 1
[sent_email] = FakeSmtp.get_mails
assert elem(email.from, 1) == sent_email.from

# assert message["from_name"] == email.from |> elem(0)
# assert message["from_email"] == email.from |> elem(1)
# assert message["subject"] == email.subject
# assert message["text"] == email.text_body
# assert message["html"] == email.html_body
# assert message["headers"] == email.headers
end

test "deliver/2 correctly formats recipients" do
end

test "raises if the response is not a success" do
end

defp new_email(attrs \\ []) do
attrs = Keyword.merge([from: "foo@bar.com", to: []], attrs)
Expand Down

0 comments on commit 9b2eca1

Please sign in to comment.