Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mandrill Template Support #176

Merged
merged 3 commits into from
Jul 1, 2016
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ Here is what it looks like:

![Screenshot of BambooEmailPreview](https://cloud.githubusercontent.com/assets/22394/14929083/bda60b76-0e29-11e6-9e11-5ec60069e825.png)

## Mandrill Specific Functionality (tags, merge vars, etc.)
## Mandrill Specific Functionality (tags, merge vars, templates, etc.)

Mandrill offers extra features on top of regular SMTP email like tagging, merge
vars, and scheduling emails to send in the future. See
vars, templates, and scheduling emails to send in the future. See
[Bamboo.MandrillHelper](https://hexdocs.pm/bamboo/Bamboo.MandrillHelper.html).

## Heroku Configuration
Expand Down
14 changes: 13 additions & 1 deletion lib/bamboo/adapters/mandrill_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ defmodule Bamboo.MandrillAdapter do

@default_base_uri "https://mandrillapp.com/"
@send_message_path "api/1.0/messages/send.json"
@send_message_template_path "api/1.0/messages/send-template.json"
@behaviour Bamboo.Adapter

defmodule ApiError do
Expand Down Expand Up @@ -56,7 +57,7 @@ defmodule Bamboo.MandrillAdapter do
def deliver(email, config) do
api_key = get_key(config)
params = email |> convert_to_mandrill_params(api_key) |> Poison.encode!
case request!(@send_message_path, params) do
case request!(api_path(email), params) do
%{status_code: status} = response when status > 299 ->
raise(ApiError, %{params: params, response: response})
response -> response
Expand Down Expand Up @@ -91,8 +92,16 @@ defmodule Bamboo.MandrillAdapter do

defp convert_to_mandrill_params(email, api_key) do
%{key: api_key, message: message_params(email)}
|> maybe_put_template_params(email)
end

defp maybe_put_template_params(params, %{private: %{template_name: template_name, template_content: template_content}}) do
params
|> Map.put(:template_name, template_name)
|> Map.put(:template_content, template_content)
end
defp maybe_put_template_params(params, _), do: params

defp message_params(email) do
%{
from_name: email.from |> elem(0),
Expand Down Expand Up @@ -130,6 +139,9 @@ defmodule Bamboo.MandrillAdapter do
end)
end

defp api_path(%{private: %{template_name: _}}), do: @send_message_template_path
defp api_path(_), do: @send_message_path

defp headers do
%{"content-type" => "application/json"}
end
Expand Down
21 changes: 20 additions & 1 deletion lib/bamboo/adapters/mandrill_helper.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Bamboo.MandrillHelper do
@moduledoc """
Functions for using features specific to Mandrill e.g. tagging, merge vars
Functions for using features specific to Mandrill e.g. tagging, merge vars, templates
"""

alias Bamboo.Email
Expand Down Expand Up @@ -48,4 +48,23 @@ defmodule Bamboo.MandrillHelper do
def tag(email, tags) do
put_param(email, "tags", List.wrap(tags))
end

@doc """
Send emails using Mandrill's template API.

Setup Mandrill to send using a named template with template content. Use this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually the first sentence of docs should be the summary of the function. So maybe something like

Send emails using Mandrill's template API

...rest of the description here

in conjuction with merge vars to offload template rendering to Mandrill. The
template name specified here must match the template name stored in Mandrill.
Mandrill's API docs for this can be found [here](https://www.mandrillapp.com/api/docs/messages.JSON.html#method=send-template).

## Example
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of adding a link in between the example and the description that links to the Mandrill page about templates?


template(email, "welcome")
template(email, "welcome", [%{"name" => "Name", "content" => "John"}])
"""
def template(email, template_name, template_content \\ []) do
email
|> Email.put_private(:template_name, template_name)
|> Email.put_private(:template_content, template_content)
end
end
37 changes: 37 additions & 0 deletions test/lib/bamboo/adapters/mandrill_adapter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ defmodule Bamboo.MandrillAdapterTest do
end
end

post "/api/1.0/messages/send-template.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
end

defp send_to_parent(conn) do
parent = Agent.get(__MODULE__, fn(set) -> HashDict.get(set, :parent) end)
send parent, {:fake_mandrill, conn}
Expand Down Expand Up @@ -78,6 +85,14 @@ defmodule Bamboo.MandrillAdapterTest do
assert request_path == "/api/1.0/messages/send.json"
end

test "deliver/2 sends the to the right url for templates" do
new_email |> MandrillHelper.template("hello") |> MandrillAdapter.deliver(@config)

assert_receive {:fake_mandrill, %{request_path: request_path}}

assert request_path == "/api/1.0/messages/send-template.json"
end

test "deliver/2 sends from, html and text body, subject, and headers" do
email = new_email(
from: {"From", "[email protected]"},
Expand Down Expand Up @@ -126,6 +141,28 @@ defmodule Bamboo.MandrillAdapterTest do
assert message["important"] == true
end

test "deliver/2 puts template name and empty content" do
email = new_email |> MandrillHelper.template("hello")

email |> MandrillAdapter.deliver(@config)

assert_receive {:fake_mandrill, %{params: %{"template_name" => template_name, "template_content" => template_content}}}
assert template_name == "hello"
assert template_content == []
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might also be worth adding a test that makes sure the template_content is populated correctly


test "deliver/2 puts template name and content" do
email = new_email |> MandrillHelper.template("hello", [
%{name: 'example name', content: 'example content'}
])

email |> MandrillAdapter.deliver(@config)

assert_receive {:fake_mandrill, %{params: %{"template_name" => template_name, "template_content" => template_content}}}
assert template_name == "hello"
assert template_content == [%{"content" => 'example content', "name" => 'example name'}]
end

test "raises if the response is not a success" do
email = new_email(from: "INVALID_EMAIL")

Expand Down
8 changes: 8 additions & 0 deletions test/lib/bamboo/adapters/mandrill_helper_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ defmodule Bamboo.MandrillHelperTest do
email = new_email |> MandrillHelper.tag(["welcome-email", "awesome"])
assert email.private.message_params == %{"tags" => ["welcome-email", "awesome"]}
end

test "adds template information to mandrill emails" do
email = new_email |> MandrillHelper.template("welcome", [%{"name" => "example_name", "content" => "example_content"}])
assert email.private == %{template_name: "welcome", template_content: [%{"name" => "example_name", "content" => "example_content"}]}

email = new_email |> MandrillHelper.template("welcome")
assert email.private == %{template_name: "welcome", template_content: []}
end
end