Repository: swoosh/swoosh
Pull request #965 (2024-11-07 19:04:57)

feat(mailjet): add event_payload to provider options
I need this feature from mailjet that is not implemented.
https://dev.mailjet.com/email/guides/send-api-v31/#tag-email-messages
I added the possibility to add an event_payload

princemaple: Cool.

Patch:
diff --git a/lib/swoosh/adapters/mailjet.ex b/lib/swoosh/adapters/mailjet.ex
index 922a6b8..62adba7 100644
--- a/lib/swoosh/adapters/mailjet.ex
+++ b/lib/swoosh/adapters/mailjet.ex
@@ -44,6 +44,8 @@ defmodule Swoosh.Adapters.Mailjet do
       |> put_provider_option(:template_error_deliver, true)
       |> put_provider_option(:template_error_reporting, "developer@example.com")
       |> put_provider_option(:variables, %{firstname: "lulu", lastname: "wang"})
+      |> put_provider_option(:custom_id, "custom_id")
+      |> put_provider_option(:event_payload, "event_payload")
 
   ## Provider options
 
@@ -61,6 +63,10 @@ defmodule Swoosh.Adapters.Mailjet do
     * `:variables` (map) - `Variables`, custom key-value variable for the email
       content
 
+    * `:custom_id` (string) - `CustomID`, custom id for the email
+
+    * `:event_payload` (string | map) - `EventPayload`, custom payload that will
+      be attached on the mailjet webhook events
   """
 
   use Swoosh.Adapter,
@@ -175,10 +181,21 @@ defmodule Swoosh.Adapters.Mailjet do
     |> prepare_template(email)
     |> prepare_custom_headers(email)
     |> prepare_custom_id(email)
+    |> prepare_event_payload(email)
   end
 
   defp wrap_messages(body) when is_list(body), do: %{Messages: body}
 
+  defp prepare_event_payload(body, %{provider_options: %{event_payload: event_payload}})
+       when is_binary(event_payload),
+       do: Map.put(body, "EventPayload", event_payload)
+
+  defp prepare_event_payload(body, %{provider_options: %{event_payload: event_payload}})
+       when is_map(event_payload),
+       do: Map.put(body, "EventPayload", Swoosh.json_library().encode!(event_payload))
+
+  defp prepare_event_payload(body, _options), do: body
+
   defp prepare_custom_id(body, %{provider_options: %{custom_id: custom_id}}),
     do: Map.put(body, "CustomID", custom_id)
 


Test patch:
diff --git a/test/swoosh/adapters/mailjet_test.exs b/test/swoosh/adapters/mailjet_test.exs
index 3d7c302..e54864c 100644
--- a/test/swoosh/adapters/mailjet_test.exs
+++ b/test/swoosh/adapters/mailjet_test.exs
@@ -12,6 +12,8 @@ defmodule Swoosh.Adapters.MailjetTest do
   @developer "developer@example.com"
   @template_id "template_id"
   @custom_id "my-great-custom-id"
+  @event_payload_binary "Eticket,1234,row,15,seat,B"
+  @event_payload_map %{"event" => "Eticket", "event_id" => "1234", "row" => "15", "seat" => "B"}
   @template_html_content "<h1>Hello, world!</h1>"
   @template_text_content "# Hello, world!"
   @success_response """
@@ -269,6 +271,102 @@ defmodule Swoosh.Adapters.MailjetTest do
     assert Mailjet.deliver(email, config) == {:ok, %{id: 123_456_789}}
   end
 
+  test "deliver/1 - valid email with binary EventPayload", %{
+    bypass: bypass,
+    config: config,
+    valid_email: email
+  } do
+    Bypass.expect(bypass, fn conn ->
+      conn = parse(conn)
+
+      body_params = %{
+        "Messages" => [
+          %{
+            "From" => %{
+              "Email" => @sender,
+              "Name" => ""
+            },
+            "To" => [
+              %{
+                "Email" => @receiver,
+                "Name" => ""
+              }
+            ],
+            "Subject" => @subject,
+            "TextPart" => @template_text_content,
+            "HTMLPart" => @template_html_content,
+            "Headers" => %{},
+            # Note: the mailjet API does not include the EventPayload
+            # it's only included in the webhook events
+            "EventPayload" => @event_payload_binary
+          }
+        ]
+      }
+
+      assert body_params == conn.body_params
+      assert "/send" == conn.request_path
+      assert "POST" == conn.method
+
+      Plug.Conn.resp(conn, 200, @success_response)
+    end)
+
+    email =
+      email
+      |> text_body(@template_text_content)
+      |> html_body(@template_html_content)
+      |> put_provider_option(:event_payload, @event_payload_binary)
+
+    assert Mailjet.deliver(email, config) == {:ok, %{id: 123_456_789}}
+  end
+
+  test "deliver/1 - valid email with map EventPayload", %{
+    bypass: bypass,
+    config: config,
+    valid_email: email
+  } do
+    Bypass.expect(bypass, fn conn ->
+      conn = parse(conn)
+
+      body_params = %{
+        "Messages" => [
+          %{
+            "From" => %{
+              "Email" => @sender,
+              "Name" => ""
+            },
+            "To" => [
+              %{
+                "Email" => @receiver,
+                "Name" => ""
+              }
+            ],
+            "Subject" => @subject,
+            "TextPart" => @template_text_content,
+            "HTMLPart" => @template_html_content,
+            "Headers" => %{},
+            # Note: the mailjet API does not include the EventPayload
+            # it's only included in the webhook events
+            "EventPayload" => Jason.encode!(@event_payload_map)
+          }
+        ]
+      }
+
+      assert body_params == conn.body_params
+      assert "/send" == conn.request_path
+      assert "POST" == conn.method
+
+      Plug.Conn.resp(conn, 200, @success_response)
+    end)
+
+    email =
+      email
+      |> text_body(@template_text_content)
+      |> html_body(@template_html_content)
+      |> put_provider_option(:event_payload, @event_payload_map)
+
+    assert Mailjet.deliver(email, config) == {:ok, %{id: 123_456_789}}
+  end
+
   test "deliver1/1 - single 4xx error response from Send API", %{
     bypass: bypass,
     config: config,