Repository: swoosh/swoosh (elixir)

Issue:
Multiple reply_to addresses (Sendgrid)
**Is your feature request related to a problem? Please describe.**
There should be a way to specify multiple addresses for `reply_to`.

**Is your feature request related to a specific adapter? Please specify.**
Sendgrid

Now there is a way to add multiple addresses in `reply_to` (at least in sendgrid) - https://docs.sendgrid.com/api-reference/mail-send/mail-send#multiple-reply-to-emails

I am thinking about preparing a PR but looks like it will affect `Email` type (which has `reply_to: mailbox() | nil`) so I am thinking how to do it and to not break everything else. Do you think it makes sense to change type to `[mailbox()] | []` and handle it everywhere?

Pull request description:
Support multiple reply_to in sendgrid
blocked by #850 

close #738 

Patch:
diff --git a/lib/swoosh/adapters/sendgrid.ex b/lib/swoosh/adapters/sendgrid.ex
index b1843f8..507bb7e 100644
--- a/lib/swoosh/adapters/sendgrid.ex
+++ b/lib/swoosh/adapters/sendgrid.ex
@@ -242,8 +242,11 @@ defmodule Swoosh.Adapters.Sendgrid do
 
   defp prepare_reply_to(body, %{reply_to: nil}), do: body
 
+  defp prepare_reply_to(body, %{reply_to: reply_to}) when is_list(reply_to),
+    do: Map.put(body, :reply_to_list, reply_to |> Enum.uniq() |> Enum.map(&email_item/1))
+
   defp prepare_reply_to(body, %{reply_to: reply_to}),
-    do: Map.put(body, :reply_to, reply_to |> email_item)
+    do: Map.put(body, :reply_to, email_item(reply_to))
 
   defp prepare_custom_headers(body, %{headers: headers})
        when map_size(headers) == 0,


Test patch:
diff --git a/test/swoosh/adapters/sendgrid_test.exs b/test/swoosh/adapters/sendgrid_test.exs
index d7b410f..23bb951 100644
--- a/test/swoosh/adapters/sendgrid_test.exs
+++ b/test/swoosh/adapters/sendgrid_test.exs
@@ -160,14 +160,8 @@ defmodule Swoosh.Adapters.SendgridTest do
       new()
       |> from({"T Stark", "tony.stark@example.com"})
       |> to({"Steve Rogers", "steve.rogers@example.com"})
-      |> reply_to("hulk.smash@example.com")
-      |> cc("hulk.smash@example.com")
-      |> cc({"Janet Pym", "wasp.avengers@example.com"})
-      |> bcc("thor.odinson@example.com")
-      |> bcc({"Henry McCoy", "beast.avengers@example.com"})
       |> subject("Hello, Avengers!")
       |> html_body("<h1>Hello</h1>")
-      |> text_body("Hello")
       |> put_provider_option(:custom_args, %{
         my_var: %{my_message_id: 123},
         my_other_var: %{my_other_id: 1, stuff: 2}
@@ -178,18 +172,9 @@ defmodule Swoosh.Adapters.SendgridTest do
 
       body_params = %{
         "from" => %{"name" => "T Stark", "email" => "tony.stark@example.com"},
-        "reply_to" => %{"email" => "hulk.smash@example.com"},
         "personalizations" => [
           %{
             "to" => [%{"name" => "Steve Rogers", "email" => "steve.rogers@example.com"}],
-            "cc" => [
-              %{"name" => "Janet Pym", "email" => "wasp.avengers@example.com"},
-              %{"email" => "hulk.smash@example.com"}
-            ],
-            "bcc" => [
-              %{"name" => "Henry McCoy", "email" => "beast.avengers@example.com"},
-              %{"email" => "thor.odinson@example.com"}
-            ],
             "custom_args" => %{
               "my_var" => %{"my_message_id" => 123},
               "my_other_var" => %{"stuff" => 2, "my_other_id" => 1}
@@ -197,7 +182,6 @@ defmodule Swoosh.Adapters.SendgridTest do
           }
         ],
         "content" => [
-          %{"type" => "text/plain", "value" => "Hello"},
           %{"type" => "text/html", "value" => "<h1>Hello</h1>"}
         ],
         "subject" => "Hello, Avengers!"
@@ -213,6 +197,45 @@ defmodule Swoosh.Adapters.SendgridTest do
     assert Sendgrid.deliver(email, config) == {:ok, %{id: "123-xyz"}}
   end
 
+  test "deliver/1 with multiple reply_to returns :ok", %{bypass: bypass, config: config} do
+    email =
+      new()
+      |> from({"T Stark", "tony.stark@example.com"})
+      |> to({"Steve Rogers", "steve.rogers@example.com"})
+      |> reply_to(["hulk.smash@example.com", "avengers.office@example.com"])
+      |> subject("Hello, Avengers!")
+      |> text_body("Hello")
+
+    Bypass.expect(bypass, fn conn ->
+      conn = parse(conn)
+
+      body_params = %{
+        "from" => %{"name" => "T Stark", "email" => "tony.stark@example.com"},
+        "reply_to_list" => [
+          %{"email" => "hulk.smash@example.com"},
+          %{"email" => "avengers.office@example.com"}
+        ],
+        "personalizations" => [
+          %{
+            "to" => [%{"name" => "Steve Rogers", "email" => "steve.rogers@example.com"}]
+          }
+        ],
+        "content" => [
+          %{"type" => "text/plain", "value" => "Hello"}
+        ],
+        "subject" => "Hello, Avengers!"
+      }
+
+      assert body_params == conn.body_params
+      assert "/mail/send" == conn.request_path
+      assert "POST" == conn.method
+
+      respond_with(conn, body: "{\"message\":\"success\"}", id: "123-xyz")
+    end)
+
+    assert Sendgrid.deliver(email, config) == {:ok, %{id: "123-xyz"}}
+  end
+
   test "deliver/1 with template_id returns :ok", %{bypass: bypass, config: config} do
     email =
       new()