Repository: swoosh/swoosh
Pull request #134 (2017-05-30 23:04:48)

Support for mail headers in Mailgun adapter
This pull request adds support for mail headers in the Mailgun adapter, sending the headers added with the function `Email.header/3` according with the Mailgun documentation (https://documentation.mailgun.com/api-sending.html#sending)

> h:X-My-Header h: prefix followed by an arbitrary value allows to append a custom MIME header to the message (X-My-Header in this case). For example, h:Reply-To to specify Reply-To address.


Patch:
diff --git a/lib/swoosh/adapters/mailgun.ex b/lib/swoosh/adapters/mailgun.ex
index bf8a91a..7493d76 100644
--- a/lib/swoosh/adapters/mailgun.ex
+++ b/lib/swoosh/adapters/mailgun.ex
@@ -66,6 +66,7 @@ defmodule Swoosh.Adapters.Mailgun do
     |> prepare_reply_to(email)
     |> prepare_attachments(email)
     |> prepare_custom_vars(email)
+    |> prepare_custom_headers(email)
     |> encode_body
   end
 
@@ -74,11 +75,14 @@ defmodule Swoosh.Adapters.Mailgun do
   # %{"my_var" => %{"my_message_id": 123},
   #   "my_other_var" => %{"my_other_id": 1, "stuff": 2}}
   defp prepare_custom_vars(body, %{provider_options: %{custom_vars: custom_vars}}) do
-    custom_vars
-    |> Enum.reduce(body, fn({k, v}, body_acc) -> Map.put(body_acc, "v:#{k}", Poison.encode!(v)) end)
+    Enum.reduce(custom_vars, body, fn {k, v}, body -> Map.put(body, "v:#{k}", Poison.encode!(v)) end)
   end
   defp prepare_custom_vars(body, _email), do: body
 
+  defp prepare_custom_headers(body, %{headers: headers}) do
+    Enum.reduce(headers, body, fn {k, v}, body -> Map.put(body, "h:#{k}", v) end)
+  end
+
   defp prepare_attachments(body, %{attachments: []}), do: body
   defp prepare_attachments(body, %{attachments: attachments}) do
     Map.put(body, :attachments, Enum.map(attachments, &prepare_file(&1)))


Test patch:
diff --git a/test/swoosh/adapters/mailgun_test.exs b/test/swoosh/adapters/mailgun_test.exs
index e19db29..3c6e05e 100644
--- a/test/swoosh/adapters/mailgun_test.exs
+++ b/test/swoosh/adapters/mailgun_test.exs
@@ -109,7 +109,36 @@ defmodule Swoosh.Adapters.MailgunTest do
     assert Mailgun.deliver(email, config) == {:ok, %{id: "<20111114174239.25659.5817@samples.mailgun.org>"}}
   end
 
+  test "delivery/1 with custom headers returns :ok", %{bypass: bypass, config: config} do
+    email =
+      new()
+      |> from("tony.stark@example.com")
+      |> to("steve.rogers@example.com")
+      |> subject("Hello, Avengers!")
+      |> html_body("<h1>Hello</h1>")
+      |> header("In-Reply-To", "<1234@example.com>")
+      |> header("X-Accept-Language", "en")
+      |> header("X-Mailer", "swoosh")
+
+    Bypass.expect bypass, fn conn ->
+      conn = parse(conn)
+      expected_path = "/" <> config[:domain] <> "/messages"
+      body_params = %{"subject" => "Hello, Avengers!",
+                      "to" => "steve.rogers@example.com",
+                      "from" => "tony.stark@example.com",
+                      "html" => "<h1>Hello</h1>",
+                      "h:In-Reply-To" => "<1234@example.com>",
+                      "h:X-Accept-Language" => "en",
+                      "h:X-Mailer" => "swoosh"}
+      assert body_params == conn.body_params
+      assert expected_path == conn.request_path
+      assert "POST" == conn.method
 
+      Plug.Conn.resp(conn, 200, @success_response)
+    end
+
+    assert Mailgun.deliver(email, config) == {:ok, %{id: "<20111114174239.25659.5817@samples.mailgun.org>"}}
+  end
 
   test "delivery/1 with 4xx response", %{bypass: bypass, config: config, valid_email: email} do
     Bypass.expect bypass, fn conn ->